Bug Summary

File:capplets/keybindings/cafe-keybinding-properties.c
Warning:line 955, column 10
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cafe-keybinding-properties.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/capplets/keybindings -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../../capplets/common -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/libxml2 -I /usr/include/cafe-desktop-2.0 -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I ../../ -D G_LOG_DOMAIN="keybinding-properties" -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/polkit-1 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gio-unix-2.0 -D CAFECC_DATA_DIR="/usr/share/cafe-control-center" -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/capplets/keybindings -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-08-06-111517-113088-1 -x c cafe-keybinding-properties.c
1/* This program was written with lots of love under the GPL by Jonathan
2 * Blandford <jrb@gnome.org>
3 */
4
5#include <config.h>
6
7#include <stdlib.h>
8#include <string.h>
9#include <ctk/ctk.h>
10#include <gio/gio.h>
11#include <cdk/cdkx.h>
12#include <X11/Xatom.h>
13#include <glib/gi18n.h>
14#include <cdk/cdkkeysyms.h>
15
16#include "wm-common.h"
17#include "capplet-util.h"
18#include "eggcellrendererkeys.h"
19#include "activate-settings-daemon.h"
20#include "dconf-util.h"
21
22#define GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/" "/org/cafe/desktop/keybindings/"
23#define CUSTOM_KEYBINDING_SCHEMA"org.cafe.control-center.keybinding" "org.cafe.control-center.keybinding"
24
25#define MAX_ELEMENTS_BEFORE_SCROLLING10 10
26#define MAX_CUSTOM_SHORTCUTS1000 1000
27#define RESPONSE_ADD0 0
28#define RESPONSE_REMOVE1 1
29
30typedef struct {
31 /* The untranslated name, combine with ->package to translate */
32 char *name;
33 /* The gettext package to use to translate the section title */
34 char *package;
35 /* Name of the window manager the keys would apply to */
36 char *wm_name;
37 /* The GSettings schema for the whole file */
38 char *schema;
39 /* an array of KeyListEntry */
40 GArray *entries;
41} KeyList;
42
43typedef enum {
44 COMPARISON_NONE = 0,
45 COMPARISON_GT,
46 COMPARISON_LT,
47 COMPARISON_EQ
48} Comparison;
49
50typedef struct
51{
52 char *gsettings_path;
53 char *schema;
54 char *name;
55 int value;
56 char *value_schema; /* gsettings schema for key/value */
57 char *value_key;
58 char *description;
59 char *description_key;
60 char *cmd_key;
61 Comparison comparison;
62} KeyListEntry;
63
64enum
65{
66 DESCRIPTION_COLUMN,
67 KEYENTRY_COLUMN,
68 N_COLUMNS
69};
70
71typedef struct
72{
73 GSettings *settings;
74 char *gsettings_path;
75 char *gsettings_key;
76 guint keyval;
77 guint keycode;
78 EggVirtualModifierType mask;
79 gboolean editable;
80 CtkTreeModel *model;
81 char *description;
82 char *desc_gsettings_key;
83 gboolean desc_editable;
84 char *command;
85 char *cmd_gsettings_key;
86 gboolean cmd_editable;
87 gulong gsettings_cnxn;
88 gulong gsettings_cnxn_desc;
89 gulong gsettings_cnxn_cmd;
90} KeyEntry;
91
92static gboolean block_accels = FALSE(0);
93static CtkWidget *custom_shortcut_dialog = NULL((void*)0);
94static CtkWidget *custom_shortcut_name_entry = NULL((void*)0);
95static CtkWidget *custom_shortcut_command_entry = NULL((void*)0);
96
97static CtkWidget* _ctk_builder_get_widget(CtkBuilder* builder, const gchar* name)
98{
99 return CTK_WIDGET (ctk_builder_get_object (builder, name))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, name))), ((ctk_widget_get_type
()))))))
;
100}
101
102static CtkBuilder *
103create_builder (void)
104{
105 CtkBuilder *builder = ctk_builder_new();
106 GError *error = NULL((void*)0);
107
108 if (ctk_builder_add_from_resource (builder, "/org/cafe/ccc/keybindings/cafe-keybinding-properties.ui", &error) == 0) {
109 g_warning ("Could not load UI: %s", error->message);
110 g_error_free (error);
111 g_object_unref (builder);
112 builder = NULL((void*)0);
113 }
114
115 return builder;
116}
117
118static char* binding_name(guint keyval, guint keycode, EggVirtualModifierType mask, gboolean translate)
119{
120 if (keyval != 0 || keycode != 0)
121 {
122 if (translate)
123 {
124 return egg_virtual_accelerator_label (keyval, keycode, mask);
125 }
126 else
127 {
128 return egg_virtual_accelerator_name (keyval, keycode, mask);
129 }
130 }
131 else
132 {
133 return g_strdup (translate ? _("Disabled") : "")g_strdup_inline (translate ? gettext ("Disabled") : "");
134 }
135}
136
137static gboolean
138binding_from_string (const char *str,
139 guint *accelerator_key,
140 guint *keycode,
141 EggVirtualModifierType *accelerator_mods)
142{
143 g_return_val_if_fail (accelerator_key != NULL, FALSE)do { if ((accelerator_key != ((void*)0))) { } else { g_return_if_fail_warning
("keybinding-properties", ((const char*) (__func__)), "accelerator_key != NULL"
); return ((0)); } } while (0)
;
144
145 if (str == NULL((void*)0) || strcmp (str, "disabled") == 0)
146 {
147 *accelerator_key = 0;
148 *keycode = 0;
149 *accelerator_mods = 0;
150 return TRUE(!(0));
151 }
152
153 egg_accelerator_parse_virtual (str, accelerator_key, keycode, accelerator_mods);
154
155 if (*accelerator_key == 0)
156 return FALSE(0);
157 else
158 return TRUE(!(0));
159}
160
161static void
162accel_set_func (CtkTreeViewColumn *tree_column,
163 CtkCellRenderer *cell,
164 CtkTreeModel *model,
165 CtkTreeIter *iter,
166 gpointer data)
167{
168 KeyEntry *key_entry;
169
170 ctk_tree_model_get (model, iter,
171 KEYENTRY_COLUMN, &key_entry,
172 -1);
173
174 if (key_entry == NULL((void*)0))
175 g_object_set (cell,
176 "visible", FALSE(0),
177 NULL((void*)0));
178 else if (! key_entry->editable)
179 g_object_set (cell,
180 "visible", TRUE(!(0)),
181 "editable", FALSE(0),
182 "accel_key", key_entry->keyval,
183 "accel_mask", key_entry->mask,
184 "keycode", key_entry->keycode,
185 "style", PANGO_STYLE_ITALIC,
186 NULL((void*)0));
187 else
188 g_object_set (cell,
189 "visible", TRUE(!(0)),
190 "editable", TRUE(!(0)),
191 "accel_key", key_entry->keyval,
192 "accel_mask", key_entry->mask,
193 "keycode", key_entry->keycode,
194 "style", PANGO_STYLE_NORMAL,
195 NULL((void*)0));
196}
197
198static void
199description_set_func (CtkTreeViewColumn *tree_column,
200 CtkCellRenderer *cell,
201 CtkTreeModel *model,
202 CtkTreeIter *iter,
203 gpointer data)
204{
205 KeyEntry *key_entry;
206
207 ctk_tree_model_get (model, iter,
208 KEYENTRY_COLUMN, &key_entry,
209 -1);
210
211 if (key_entry != NULL((void*)0))
212 g_object_set (cell,
213 "editable", FALSE(0),
214 "text", key_entry->description != NULL((void*)0) ?
215 key_entry->description : _("<Unknown Action>")gettext ("<Unknown Action>"),
216 NULL((void*)0));
217 else
218 g_object_set (cell,
219 "editable", FALSE(0), NULL((void*)0));
220}
221
222static gboolean
223keybinding_key_changed_foreach (CtkTreeModel *model,
224 CtkTreePath *path,
225 CtkTreeIter *iter,
226 gpointer user_data)
227{
228 KeyEntry *key_entry;
229 KeyEntry *tmp_key_entry;
230
231 key_entry = (KeyEntry *)user_data;
232 ctk_tree_model_get (key_entry->model, iter,
233 KEYENTRY_COLUMN, &tmp_key_entry,
234 -1);
235
236 if (key_entry == tmp_key_entry)
237 {
238 ctk_tree_model_row_changed (key_entry->model, path, iter);
239 return TRUE(!(0));
240 }
241 return FALSE(0);
242}
243
244static void
245keybinding_key_changed (GSettings *settings,
246 gchar *key,
247 KeyEntry *key_entry)
248{
249 gchar *key_value;
250
251 key_value = g_settings_get_string (settings, key);
252
253 binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
254 key_entry->editable = g_settings_is_writable (settings, key);
255
256 /* update the model */
257 ctk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry);
258}
259
260static void
261keybinding_description_changed (GSettings *settings,
262 gchar *key,
263 KeyEntry *key_entry)
264{
265 gchar *key_value;
266
267 key_value = g_settings_get_string (settings, key);
268
269 g_free (key_entry->description);
270 key_entry->description = key_value ? g_strdup (key_value)g_strdup_inline (key_value) : NULL((void*)0);
271 g_free (key_value);
272
273 key_entry->desc_editable = g_settings_is_writable (settings, key);
274
275 /* update the model */
276 ctk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry);
277}
278
279static void
280keybinding_command_changed (GSettings *settings,
281 gchar *key,
282 KeyEntry *key_entry)
283{
284 gchar *key_value;
285
286 key_value = g_settings_get_string (settings, key);
287
288 g_free (key_entry->command);
289 key_entry->command = key_value ? g_strdup (key_value)g_strdup_inline (key_value) : NULL((void*)0);
290 key_entry->cmd_editable = g_settings_is_writable (settings, key);
291 g_free (key_value);
292
293 /* update the model */
294 ctk_tree_model_foreach (key_entry->model, keybinding_key_changed_foreach, key_entry);
295}
296
297static int
298keyentry_sort_func (CtkTreeModel *model,
299 CtkTreeIter *a,
300 CtkTreeIter *b,
301 gpointer user_data)
302{
303 KeyEntry *key_entry_a;
304 KeyEntry *key_entry_b;
305 int retval;
306
307 key_entry_a = NULL((void*)0);
308 ctk_tree_model_get (model, a,
309 KEYENTRY_COLUMN, &key_entry_a,
310 -1);
311
312 key_entry_b = NULL((void*)0);
313 ctk_tree_model_get (model, b,
314 KEYENTRY_COLUMN, &key_entry_b,
315 -1);
316
317 if (key_entry_a && key_entry_b)
318 {
319 if ((key_entry_a->keyval || key_entry_a->keycode) &&
320 (key_entry_b->keyval || key_entry_b->keycode))
321 {
322 gchar *name_a, *name_b;
323
324 name_a = binding_name (key_entry_a->keyval,
325 key_entry_a->keycode,
326 key_entry_a->mask,
327 TRUE(!(0)));
328
329 name_b = binding_name (key_entry_b->keyval,
330 key_entry_b->keycode,
331 key_entry_b->mask,
332 TRUE(!(0)));
333
334 retval = g_utf8_collate (name_a, name_b);
335
336 g_free (name_a);
337 g_free (name_b);
338 }
339 else if (key_entry_a->keyval || key_entry_a->keycode)
340 retval = -1;
341 else if (key_entry_b->keyval || key_entry_b->keycode)
342 retval = 1;
343 else
344 retval = 0;
345 }
346 else if (key_entry_a)
347 retval = -1;
348 else if (key_entry_b)
349 retval = 1;
350 else
351 retval = 0;
352
353 return retval;
354}
355
356static void
357clear_old_model (CtkBuilder *builder)
358{
359 CtkWidget *tree_view;
360 CtkWidget *actions_swindow;
361 CtkTreeModel *model;
362
363 tree_view = _ctk_builder_get_widget (builder, "shortcut_treeview");
364 model = ctk_tree_view_get_model (CTK_TREE_VIEW (tree_view)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_tree_view_get_type ()))))))
);
365
366 if (model == NULL((void*)0))
367 {
368 /* create a new model */
369 model = (CtkTreeModel *) ctk_tree_store_new (N_COLUMNS, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_POINTER((GType) ((17) << (2))));
370
371 ctk_tree_sortable_set_sort_func (CTK_TREE_SORTABLE (model)((((CtkTreeSortable*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_sortable_get_type ()))))))
,
372 KEYENTRY_COLUMN,
373 keyentry_sort_func,
374 NULL((void*)0), NULL((void*)0));
375
376 ctk_tree_view_set_model (CTK_TREE_VIEW (tree_view)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_tree_view_get_type ()))))))
, model);
377
378 g_object_unref (model);
379 }
380 else
381 {
382 /* clear the existing model */
383 gboolean valid;
384 CtkTreeIter iter;
385 KeyEntry *key_entry;
386
387 for (valid = ctk_tree_model_get_iter_first (model, &iter);
388 valid;
389 valid = ctk_tree_model_iter_next (model, &iter))
390 {
391 ctk_tree_model_get (model, &iter,
392 KEYENTRY_COLUMN, &key_entry,
393 -1);
394
395 if (key_entry != NULL((void*)0))
396 {
397 g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn);
398 if (key_entry->gsettings_cnxn_desc != 0)
399 g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn_desc);
400 if (key_entry->gsettings_cnxn_cmd != 0)
401 g_signal_handler_disconnect (key_entry->settings, key_entry->gsettings_cnxn_cmd);
402
403 g_object_unref (key_entry->settings);
404 if (key_entry->gsettings_path)
405 g_free (key_entry->gsettings_path);
406 g_free (key_entry->gsettings_key);
407 g_free (key_entry->description);
408 g_free (key_entry->desc_gsettings_key);
409 g_free (key_entry->command);
410 g_free (key_entry->cmd_gsettings_key);
411 g_free (key_entry);
412 }
413 }
414
415 ctk_tree_store_clear (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
);
416 }
417
418 actions_swindow = _ctk_builder_get_widget (builder, "actions_swindow");
419 ctk_scrolled_window_set_policy (CTK_SCROLLED_WINDOW (actions_swindow)((((CtkScrolledWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((actions_swindow)), ((ctk_scrolled_window_get_type
()))))))
,
420 CTK_POLICY_NEVER, CTK_POLICY_NEVER);
421 ctk_widget_set_size_request (actions_swindow, -1, -1);
422}
423
424typedef struct {
425 const char *key;
426 const char *path;
427 const char *schema;
428 gboolean found;
429} KeyMatchData;
430
431static gboolean key_match(CtkTreeModel* model, CtkTreePath* path, CtkTreeIter* iter, gpointer data)
432{
433 KeyMatchData* match_data = data;
434 KeyEntry* element = NULL((void*)0);
435 gchar *element_schema = NULL((void*)0);
436 gchar *element_path = NULL((void*)0);
437
438 ctk_tree_model_get(model, iter,
439 KEYENTRY_COLUMN, &element,
440 -1);
441
442 if (element && element->settings && G_IS_SETTINGS(element->settings)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(element->settings)); GType __t = ((g_settings_get_type ()
)); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
443 {
444 g_object_get (element->settings, "schema-id", &element_schema, NULL((void*)0));
445 g_object_get (element->settings, "path", &element_path, NULL((void*)0));
446 }
447
448 if (element && g_strcmp0(element->gsettings_key, match_data->key) == 0
449 && g_strcmp0(element_schema, match_data->schema) == 0
450 && g_strcmp0(element_path, match_data->path) == 0)
451 {
452 match_data->found = TRUE(!(0));
453 return TRUE(!(0));
454 }
455
456 return FALSE(0);
457}
458
459static gboolean key_is_already_shown(CtkTreeModel* model, const KeyListEntry* entry)
460{
461 KeyMatchData data;
462
463 data.key = entry->name;
464 data.schema = entry->schema;
465 data.path = entry->gsettings_path;
466 data.found = FALSE(0);
467 ctk_tree_model_foreach(model, key_match, &data);
468
469 return data.found;
470}
471
472static gboolean should_show_key(const KeyListEntry* entry)
473{
474 GSettings *settings;
475 int value;
476
477 if (entry->comparison == COMPARISON_NONE)
478 {
479 return TRUE(!(0));
480 }
481
482 g_return_val_if_fail(entry->value_key != NULL, FALSE)do { if ((entry->value_key != ((void*)0))) { } else { g_return_if_fail_warning
("keybinding-properties", ((const char*) (__func__)), "entry->value_key != NULL"
); return ((0)); } } while (0)
;
483 g_return_val_if_fail(entry->value_schema != NULL, FALSE)do { if ((entry->value_schema != ((void*)0))) { } else { g_return_if_fail_warning
("keybinding-properties", ((const char*) (__func__)), "entry->value_schema != NULL"
); return ((0)); } } while (0)
;
484
485 settings = g_settings_new (entry->value_schema);
486 value = g_settings_get_int (settings, entry->value_key);
487 g_object_unref (settings);
488
489 switch (entry->comparison)
490 {
491 case COMPARISON_NONE:
492 /* For compiler warnings */
493 g_assert_not_reached ()do { g_assertion_message_expr ("keybinding-properties", "cafe-keybinding-properties.c"
, 493, ((const char*) (__func__)), ((void*)0)); } while (0)
;
494 return FALSE(0);
495 case COMPARISON_GT:
496 if (value > entry->value)
497 {
498 return TRUE(!(0));
499 }
500 break;
501 case COMPARISON_LT:
502 if (value < entry->value)
503 {
504 return TRUE(!(0));
505 }
506 break;
507 case COMPARISON_EQ:
508 if (value == entry->value)
509 {
510 return TRUE(!(0));
511 }
512 break;
513 }
514
515 return FALSE(0);
516}
517
518static gboolean
519count_rows_foreach (CtkTreeModel *model, CtkTreePath *path, CtkTreeIter *iter, gpointer data)
520{
521 gint *rows = data;
522
523 (*rows)++;
524
525 return FALSE(0);
526}
527
528static void
529ensure_scrollbar (CtkBuilder *builder, int i)
530{
531 if (i == MAX_ELEMENTS_BEFORE_SCROLLING10)
532 {
533 CtkRequisition rectangle;
534 GObject *actions_swindow = ctk_builder_get_object (builder,
535 "actions_swindow");
536 CtkWidget *treeview = _ctk_builder_get_widget (builder,
537 "shortcut_treeview");
538 ctk_widget_get_preferred_size (treeview, &rectangle, NULL((void*)0));
539 ctk_widget_set_size_request (treeview, -1, rectangle.height);
540 ctk_scrolled_window_set_policy (CTK_SCROLLED_WINDOW (actions_swindow)((((CtkScrolledWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((actions_swindow)), ((ctk_scrolled_window_get_type
()))))))
,
541 CTK_POLICY_NEVER, CTK_POLICY_AUTOMATIC);
542 }
543}
544
545static void
546find_section (CtkTreeModel *model,
547 CtkTreeIter *iter,
548 const char *title)
549{
550 gboolean success;
551
552 success = ctk_tree_model_get_iter_first (model, iter);
553 while (success)
554 {
555 char *description = NULL((void*)0);
556
557 ctk_tree_model_get (model, iter,
558 DESCRIPTION_COLUMN, &description,
559 -1);
560
561 if (g_strcmp0 (description, title) == 0)
562 return;
563 success = ctk_tree_model_iter_next (model, iter);
564 }
565
566 ctk_tree_store_append (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, iter, NULL((void*)0));
567 ctk_tree_store_set (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, iter,
568 DESCRIPTION_COLUMN, title,
569 -1);
570}
571
572static void
573append_keys_to_tree (CtkBuilder *builder,
574 const gchar *title,
575 const gchar *schema,
576 const gchar *package,
577 const KeyListEntry *keys_list)
578{
579 CtkTreeIter parent_iter, iter;
580 CtkTreeModel *model;
581 gint i, j;
582
583 model = ctk_tree_view_get_model (CTK_TREE_VIEW (ctk_builder_get_object (builder, "shortcut_treeview"))((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
);
584
585 /* Try to find a section parent iter, if it already exists */
586 find_section (model, &iter, title);
587 parent_iter = iter;
588
589 i = 0;
590 ctk_tree_model_foreach (model, count_rows_foreach, &i);
591
592 /* If the header we just added is the MAX_ELEMENTS_BEFORE_SCROLLING th,
593 * then we need to scroll now */
594 ensure_scrollbar (builder, i - 1);
595
596 for (j = 0; keys_list[j].name != NULL((void*)0); j++)
597 {
598 GSettings *settings = NULL((void*)0);
599 gchar *settings_path;
600 KeyEntry *key_entry;
601 const gchar *key_string;
602 gchar *key_value;
603 gchar *description;
604 gchar *command;
605
606 if (!should_show_key (&keys_list[j]))
607 continue;
608
609 if (key_is_already_shown (model, &keys_list[j]))
610 continue;
611
612 key_string = keys_list[j].name;
613
614 if (keys_list[j].gsettings_path != NULL((void*)0))
615 {
616 settings = g_settings_new_with_path (schema, keys_list[j].gsettings_path);
617 settings_path = g_strdup(keys_list[j].gsettings_path)g_strdup_inline (keys_list[j].gsettings_path);
618 }
619 else
620 {
621 settings = g_settings_new (schema);
622 settings_path = NULL((void*)0);
623 }
624
625 if (keys_list[j].description_key != NULL((void*)0))
626 {
627 /* it's a custom shortcut, so description is in gsettings */
628 description = g_settings_get_string (settings, keys_list[j].description_key);
629 }
630 else
631 {
632 /* it's from keyfile, so description need to be translated */
633 description = keys_list[j].description;
634 if (package)
635 {
636 bind_textdomain_codeset (package, "UTF-8");
637 description = dgettext (package, description);
638 }
639 else
640 {
641 description = _(description)gettext (description);
642 }
643 }
644
645 if (description == NULL((void*)0))
646 {
647 /* Only print a warning for keys that should have a schema */
648 if (keys_list[j].description_key == NULL((void*)0))
649 g_warning ("No description for key '%s'", key_string);
650 }
651
652
653
654 if (keys_list[j].cmd_key != NULL((void*)0))
655 {
656 command = g_settings_get_string (settings, keys_list[j].cmd_key);
657 }
658 else
659 {
660 command = NULL((void*)0);
661 }
662
663 key_entry = g_new0 (KeyEntry, 1)((KeyEntry *) g_malloc0_n ((1), sizeof (KeyEntry)));
664 key_entry->settings = settings;
665 key_entry->gsettings_path = settings_path;
666 key_entry->gsettings_key = g_strdup (key_string)g_strdup_inline (key_string);
667 key_entry->editable = g_settings_is_writable (settings, key_string);
668 key_entry->model = model;
669 key_entry->description = description;
670 key_entry->command = command;
671 if (keys_list[j].description_key != NULL((void*)0))
672 {
673 key_entry->desc_gsettings_key = g_strdup (keys_list[j].description_key)g_strdup_inline (keys_list[j].description_key);
674 key_entry->desc_editable = g_settings_is_writable (settings, key_entry->desc_gsettings_key);
675 gchar *gsettings_signal = g_strconcat ("changed::", key_entry->desc_gsettings_key, NULL((void*)0));
676 key_entry->gsettings_cnxn_desc = g_signal_connect (settings,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_description_changed))), (key_entry), ((void*)0)
, (GConnectFlags) 0)
677 gsettings_signal,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_description_changed))), (key_entry), ((void*)0)
, (GConnectFlags) 0)
678 G_CALLBACK (keybinding_description_changed),g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_description_changed))), (key_entry), ((void*)0)
, (GConnectFlags) 0)
679 key_entry)g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_description_changed))), (key_entry), ((void*)0)
, (GConnectFlags) 0)
;
680 g_free (gsettings_signal);
681 }
682 if (keys_list[j].cmd_key != NULL((void*)0))
683 {
684 key_entry->cmd_gsettings_key = g_strdup (keys_list[j].cmd_key)g_strdup_inline (keys_list[j].cmd_key);
685 key_entry->cmd_editable = g_settings_is_writable (settings, key_entry->cmd_gsettings_key);
686 gchar *gsettings_signal = g_strconcat ("changed::", key_entry->cmd_gsettings_key, NULL((void*)0));
687 key_entry->gsettings_cnxn_cmd = g_signal_connect (settings,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_command_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
688 gsettings_signal,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_command_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
689 G_CALLBACK (keybinding_command_changed),g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_command_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
690 key_entry)g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_command_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
;
691 g_free (gsettings_signal);
692 }
693
694 gchar *gsettings_signal = g_strconcat ("changed::", key_string, NULL((void*)0));
695 key_entry->gsettings_cnxn = g_signal_connect (settings,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_key_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
696 gsettings_signal,g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_key_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
697 G_CALLBACK (keybinding_key_changed),g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_key_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
698 key_entry)g_signal_connect_data ((settings), (gsettings_signal), (((GCallback
) (keybinding_key_changed))), (key_entry), ((void*)0), (GConnectFlags
) 0)
;
699 g_free (gsettings_signal);
700
701 key_value = g_settings_get_string (settings, key_string);
702 binding_from_string (key_value, &key_entry->keyval, &key_entry->keycode, &key_entry->mask);
703 g_free (key_value);
704
705 ensure_scrollbar (builder, i);
706
707 ++i;
708 ctk_tree_store_append (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &iter, &parent_iter);
709 /* we use the DESCRIPTION_COLUMN only for the section headers */
710 ctk_tree_store_set (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &iter,
711 KEYENTRY_COLUMN, key_entry,
712 -1);
713 ctk_tree_view_expand_all (CTK_TREE_VIEW (ctk_builder_get_object (builder, "shortcut_treeview"))((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
);
714 }
715
716 /* Don't show an empty section */
717 if (ctk_tree_model_iter_n_children (model, &parent_iter) == 0)
718 ctk_tree_store_remove (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &parent_iter);
719
720 if (i == 0)
721 ctk_widget_hide (_ctk_builder_get_widget (builder, "shortcuts_vbox"));
722 else
723 ctk_widget_show (_ctk_builder_get_widget (builder, "shortcuts_vbox"));
724}
725
726static void
727parse_start_tag (GMarkupParseContext *ctx,
728 const gchar *element_name,
729 const gchar **attr_names,
730 const gchar **attr_values,
731 gpointer user_data,
732 GError **error)
733{
734 KeyList *keylist = (KeyList *) user_data;
735 KeyListEntry key;
736 const char *name, *value_key, *description, *value_schema;
737 int value;
738 Comparison comparison;
739 const char *schema = NULL((void*)0);
740
741 name = NULL((void*)0);
742
743 /* The top-level element, names the section in the tree */
744 if (g_str_equal (element_name, "KeyListEntries")(strcmp ((const char *) (element_name), (const char *) ("KeyListEntries"
)) == 0)
)
745 {
746 const char *wm_name = NULL((void*)0);
747 const char *package = NULL((void*)0);
748
749 while (*attr_names && *attr_values)
750 {
751 if (g_str_equal (*attr_names, "name")(strcmp ((const char *) (*attr_names), (const char *) ("name"
)) == 0)
)
752 {
753 if (**attr_values)
754 name = *attr_values;
755 }
756 else if (g_str_equal (*attr_names, "wm_name")(strcmp ((const char *) (*attr_names), (const char *) ("wm_name"
)) == 0)
)
757 {
758 if (**attr_values)
759 wm_name = *attr_values;
760 }
761 else if (g_str_equal (*attr_names, "package")(strcmp ((const char *) (*attr_names), (const char *) ("package"
)) == 0)
)
762 {
763 if (**attr_values)
764 package = *attr_values;
765 }
766 else if (g_str_equal (*attr_names, "schema")(strcmp ((const char *) (*attr_names), (const char *) ("schema"
)) == 0)
)
767 {
768 if (**attr_values)
769 schema = *attr_values;
770 }
771 ++attr_names;
772 ++attr_values;
773 }
774
775 if (name)
776 {
777 if (keylist->name)
778 g_warning ("Duplicate section name");
779 g_free (keylist->name);
780 keylist->name = g_strdup (name)g_strdup_inline (name);
781 }
782 if (wm_name)
783 {
784 if (keylist->wm_name)
785 g_warning ("Duplicate window manager name");
786 g_free (keylist->wm_name);
787 keylist->wm_name = g_strdup (wm_name)g_strdup_inline (wm_name);
788 }
789 if (package)
790 {
791 if (keylist->package)
792 g_warning ("Duplicate gettext package name");
793 g_free (keylist->package);
794 keylist->package = g_strdup (package)g_strdup_inline (package);
795 }
796 if (schema)
797 {
798 if (keylist->schema)
799 g_warning ("Duplicate schema name");
800 g_free (keylist->schema);
801 keylist->schema = g_strdup (schema)g_strdup_inline (schema);
802 }
803 return;
804 }
805
806 if (!g_str_equal (element_name, "KeyListEntry")(strcmp ((const char *) (element_name), (const char *) ("KeyListEntry"
)) == 0)
807 || attr_names == NULL((void*)0)
808 || attr_values == NULL((void*)0))
809 return;
810
811 value = 0;
812 comparison = COMPARISON_NONE;
813 value_key = NULL((void*)0);
814 value_schema = NULL((void*)0);
815 description = NULL((void*)0);
816
817 while (*attr_names && *attr_values)
818 {
819 if (g_str_equal (*attr_names, "name")(strcmp ((const char *) (*attr_names), (const char *) ("name"
)) == 0)
)
820 {
821 /* skip if empty */
822 if (**attr_values)
823 name = *attr_values;
824 } else if (g_str_equal (*attr_names, "value")(strcmp ((const char *) (*attr_names), (const char *) ("value"
)) == 0)
) {
825 if (**attr_values) {
826 value = (int) g_ascii_strtoull (*attr_values, NULL((void*)0), 0);
827 }
828 } else if (g_str_equal (*attr_names, "key")(strcmp ((const char *) (*attr_names), (const char *) ("key")
) == 0)
) {
829 if (**attr_values) {
830 value_key = *attr_values;
831 }
832 } else if (g_str_equal (*attr_names, "comparison")(strcmp ((const char *) (*attr_names), (const char *) ("comparison"
)) == 0)
) {
833 if (**attr_values) {
834 if (g_str_equal (*attr_values, "gt")(strcmp ((const char *) (*attr_values), (const char *) ("gt")
) == 0)
) {
835 comparison = COMPARISON_GT;
836 } else if (g_str_equal (*attr_values, "lt")(strcmp ((const char *) (*attr_values), (const char *) ("lt")
) == 0)
) {
837 comparison = COMPARISON_LT;
838 } else if (g_str_equal (*attr_values, "eq")(strcmp ((const char *) (*attr_values), (const char *) ("eq")
) == 0)
) {
839 comparison = COMPARISON_EQ;
840 }
841 }
842 } else if (g_str_equal (*attr_names, "description")(strcmp ((const char *) (*attr_names), (const char *) ("description"
)) == 0)
) {
843 if (**attr_values) {
844 description = *attr_values;
845 }
846 } else if (g_str_equal (*attr_names, "schema")(strcmp ((const char *) (*attr_names), (const char *) ("schema"
)) == 0)
) {
847 if (**attr_values) {
848 value_schema = *attr_values;
849 }
850 }
851
852 ++attr_names;
853 ++attr_values;
854 }
855
856 if (name == NULL((void*)0))
857 return;
858
859 key.name = g_strdup (name)g_strdup_inline (name);
860 key.gsettings_path = NULL((void*)0);
861 key.description_key = NULL((void*)0);
862 key.description = g_strdup(description)g_strdup_inline (description);
863 key.schema = g_strdup(schema)g_strdup_inline (schema);
864 key.value = value;
865 if (value_key) {
866 key.value_key = g_strdup (value_key)g_strdup_inline (value_key);
867 key.value_schema = g_strdup (value_schema)g_strdup_inline (value_schema);
868 }
869 else {
870 key.value_key = NULL((void*)0);
871 key.value_schema = NULL((void*)0);
872 }
873 key.comparison = comparison;
874 key.cmd_key = NULL((void*)0);
875 g_array_append_val (keylist->entries, key)g_array_append_vals (keylist->entries, &(key), 1);
876}
877
878static gboolean
879strv_contains (char **strv,
880 char *str)
881{
882 char **p = strv;
883 for (p = strv; *p; p++)
884 if (strcmp (*p, str) == 0)
885 return TRUE(!(0));
886
887 return FALSE(0);
888}
889
890static void
891append_keys_to_tree_from_file (CtkBuilder *builder,
892 const char *filename,
893 char **wm_keybindings)
894{
895 GMarkupParseContext *ctx;
896 GMarkupParser parser = { parse_start_tag, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0) };
897 KeyList *keylist;
898 KeyListEntry key, *keys;
899 GError *err = NULL((void*)0);
900 char *buf;
901 const char *title;
902 gsize buf_len;
903 guint i;
904
905 if (!g_file_get_contents (filename, &buf, &buf_len, &err))
906 return;
907
908 keylist = g_new0 (KeyList, 1)((KeyList *) g_malloc0_n ((1), sizeof (KeyList)));
909 keylist->entries = g_array_new (FALSE(0), TRUE(!(0)), sizeof (KeyListEntry));
910 ctx = g_markup_parse_context_new (&parser, 0, keylist, NULL((void*)0));
911
912 if (!g_markup_parse_context_parse (ctx, buf, buf_len, &err))
913 {
914 g_warning ("Failed to parse '%s': '%s'", filename, err->message);
915 g_error_free (err);
916 g_free (keylist->name);
917 g_free (keylist->package);
918 g_free (keylist->wm_name);
919 g_free (keylist->schema);
920 for (i = 0; i < keylist->entries->len; i++)
921 g_free (((KeyListEntry *) &(keylist->entries->data[i]))->name);
922 g_array_free (keylist->entries, TRUE(!(0)));
923 g_free (keylist);
924 keylist = NULL((void*)0);
925 }
926 g_markup_parse_context_free (ctx);
927 g_free (buf);
928
929 if (keylist == NULL((void*)0))
930 return;
931
932 /* If there's no keys to add, or the settings apply to a window manager
933 * that's not the one we're running */
934 if (keylist->entries->len == 0
935 || (keylist->wm_name != NULL((void*)0) && !strv_contains (wm_keybindings, keylist->wm_name))
936 || keylist->name == NULL((void*)0))
937 {
938 g_free (keylist->name);
939 g_free (keylist->package);
940 g_free (keylist->wm_name);
941 g_free (keylist->schema);
942 g_array_free (keylist->entries, TRUE(!(0)));
943 g_free (keylist);
944 return;
945 }
946
947 /* Empty KeyListEntry to end the array */
948 key.name = NULL((void*)0);
949 key.description_key = NULL((void*)0);
950 key.value_key = NULL((void*)0);
951 key.value = 0;
952 key.comparison = COMPARISON_NONE;
953 g_array_append_val (keylist->entries, key)g_array_append_vals (keylist->entries, &(key), 1);
954
955 keys = (KeyListEntry *) g_array_free (keylist->entries, FALSE(0));
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
956 if (keylist->package)
957 {
958 bind_textdomain_codeset (keylist->package, "UTF-8");
959 title = dgettext (keylist->package, keylist->name);
960 } else {
961 title = _(keylist->name)gettext (keylist->name);
962 }
963
964 append_keys_to_tree (builder, title, keylist->schema, keylist->package, keys);
965
966 g_free (keylist->name);
967 g_free (keylist->package);
968 for (i = 0; keys[i].name != NULL((void*)0); i++)
969 g_free (keys[i].name);
970 g_free (keylist);
971}
972
973static void
974append_keys_to_tree_from_gsettings (CtkBuilder *builder, const gchar *gsettings_path)
975{
976 gchar **custom_list;
977 GArray *entries;
978 KeyListEntry key;
979 guint i;
980
981 /* load custom shortcuts from GSettings */
982 entries = g_array_new (FALSE(0), TRUE(!(0)), sizeof (KeyListEntry));
983
984 key.value_key = NULL((void*)0);
985 key.value = 0;
986 key.comparison = COMPARISON_NONE;
987
988 custom_list = dconf_util_list_subdirs (gsettings_path, FALSE(0));
989
990 if (custom_list != NULL((void*)0))
991 {
992 for (i = 0; custom_list[i] != NULL((void*)0); i++)
993 {
994 key.gsettings_path = g_strdup_printf("%s%s", gsettings_path, custom_list[i]);
995 key.name = g_strdup("binding")g_strdup_inline ("binding");
996 key.cmd_key = g_strdup("action")g_strdup_inline ("action");
997 key.description_key = g_strdup("name")g_strdup_inline ("name");
998 key.schema = NULL((void*)0);
999 g_array_append_val (entries, key)g_array_append_vals (entries, &(key), 1);
1000 }
1001 }
1002
1003 g_strfreev (custom_list);
1004
1005 if (entries->len > 0)
1006 {
1007 KeyListEntry *keys;
1008
1009 /* Empty KeyListEntry to end the array */
1010 key.gsettings_path = NULL((void*)0);
1011 key.name = NULL((void*)0);
1012 key.description_key = NULL((void*)0);
1013 key.cmd_key = NULL((void*)0);
1014 g_array_append_val (entries, key)g_array_append_vals (entries, &(key), 1);
1015
1016 keys = (KeyListEntry *) entries->data;
1017 append_keys_to_tree (builder, _("Custom Shortcuts")gettext ("Custom Shortcuts"), CUSTOM_KEYBINDING_SCHEMA"org.cafe.control-center.keybinding", NULL((void*)0), keys);
1018 for (i = 0; i < entries->len; ++i)
1019 {
1020 g_free (keys[i].name);
1021 g_free (keys[i].description_key);
1022 g_free (keys[i].cmd_key);
1023 g_free (keys[i].gsettings_path);
1024 }
1025 }
1026
1027 g_array_free (entries, TRUE(!(0)));
1028}
1029
1030static void
1031reload_key_entries (CtkBuilder *builder)
1032{
1033 gchar **wm_keybindings;
1034 GList *list, *l;
1035 const gchar * const * data_dirs;
1036 GHashTable *loaded_files;
1037 guint i;
1038
1039 wm_keybindings = wm_common_get_current_keybindings();
1040
1041 clear_old_model (builder);
1042
1043 loaded_files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1044 data_dirs = g_get_system_data_dirs ();
1045 for (i = 0; data_dirs[i] != NULL((void*)0); i++)
1046 {
1047 g_autofree__attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) gchar *dir_path = NULL((void*)0);
1048 GDir *dir;
1049 const gchar *name;
1050
1051 dir_path = g_build_filename (data_dirs[i], "cafe-control-center", "keybindings", NULL((void*)0));
1052 g_debug ("Keybinding dir: %s", dir_path);
1053
1054 dir = g_dir_open (dir_path, 0, NULL((void*)0));
1055 if (!dir)
1056 continue;
1057
1058 for (name = g_dir_read_name (dir) ; name ; name = g_dir_read_name (dir))
1059 {
1060 if (g_str_has_suffix (name, ".xml")(__builtin_constant_p (".xml")? __extension__ ({ const char *
const __str = (name); const char * const __suffix = (".xml")
; gboolean __result = (0); if (__str == ((void*)0) || __suffix
== ((void*)0)) __result = (g_str_has_suffix) (__str, __suffix
); else { const size_t __str_len = strlen (((__str) + !(__str
))); const size_t __suffix_len = strlen (((__suffix) + !(__suffix
))); if (__str_len >= __suffix_len) __result = memcmp (__str
+ __str_len - __suffix_len, ((__suffix) + !(__suffix)), __suffix_len
) == 0; } __result; }) : (g_str_has_suffix) (name, ".xml") )
== FALSE(0))
1061 continue;
1062
1063 if (g_hash_table_lookup (loaded_files, name) != NULL((void*)0))
1064 {
1065 g_debug ("Not loading %s, it was already loaded from another directory", name);
1066 continue;
1067 }
1068
1069 g_hash_table_insert (loaded_files, g_strdup (name)g_strdup_inline (name), g_strdup (dir_path)g_strdup_inline (dir_path));
1070 }
1071
1072 g_dir_close (dir);
1073 }
1074 list = g_hash_table_get_keys (loaded_files);
1075 list = g_list_sort(list, (GCompareFunc) g_str_equal);
1076 for (l = list; l != NULL((void*)0); l = l->next)
1077 {
1078 g_autofree__attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) gchar *path = NULL((void*)0);
1079 path = g_build_filename (g_hash_table_lookup (loaded_files, l->data), l->data, NULL((void*)0));
1080 g_debug ("Keybinding file: %s", path);
1081 append_keys_to_tree_from_file (builder, path, wm_keybindings);
1082 }
1083 g_list_free (list);
1084 g_hash_table_destroy (loaded_files);
1085
1086 /* Load custom shortcuts _after_ system-provided ones,
1087 * since some of the custom shortcuts may also be listed
1088 * in a file. Loading the custom shortcuts last makes
1089 * such keys not show up in the custom section.
1090 */
1091 append_keys_to_tree_from_gsettings (builder, GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/");
1092
1093 g_strfreev (wm_keybindings);
1094}
1095
1096static void
1097key_entry_controlling_key_changed (GSettings *settings, gchar *key, gpointer user_data)
1098{
1099 reload_key_entries (user_data);
1100}
1101
1102static gboolean cb_check_for_uniqueness(CtkTreeModel* model, CtkTreePath* path, CtkTreeIter* iter, KeyEntry* new_key)
1103{
1104 KeyEntry* element;
1105
1106 ctk_tree_model_get (new_key->model, iter,
1107 KEYENTRY_COLUMN, &element,
1108 -1);
1109
1110 /* no conflict for : blanks, different modifiers, or ourselves */
1111 if (element == NULL((void*)0) || new_key->mask != element->mask)
1112 {
1113 return FALSE(0);
1114 }
1115
1116 gchar *new_key_schema = NULL((void*)0);
1117 gchar *element_schema = NULL((void*)0);
1118 gchar *new_key_path = NULL((void*)0);
1119 gchar *element_path = NULL((void*)0);
1120
1121 if (new_key && new_key->settings)
1122 {
1123 g_object_get (new_key->settings, "schema-id", &new_key_schema, NULL((void*)0));
1124 g_object_get (new_key->settings, "path", &new_key_path, NULL((void*)0));
1125 }
1126
1127 if (element->settings)
1128 {
1129 g_object_get (element->settings, "schema-id", &element_schema, NULL((void*)0));
1130 g_object_get (element->settings, "path", &element_path, NULL((void*)0));
1131 }
1132
1133 if (!g_strcmp0 (new_key->gsettings_key, element->gsettings_key) &&
1134 !g_strcmp0 (new_key_schema, element_schema) &&
1135 !g_strcmp0 (new_key_path, element_path))
1136 {
1137 return FALSE(0);
1138 }
1139
1140 if (new_key->keyval != 0)
1141 {
1142 if (new_key->keyval != element->keyval)
1143 {
1144 return FALSE(0);
1145 }
1146 }
1147 else if (element->keyval != 0 || new_key->keycode != element->keycode)
1148 {
1149 return FALSE(0);
1150 }
1151
1152 new_key->editable = FALSE(0);
1153 new_key->settings = element->settings;
1154 new_key->gsettings_key = element->gsettings_key;
1155 new_key->description = element->description;
1156 new_key->desc_gsettings_key = element->desc_gsettings_key;
1157 new_key->desc_editable = element->desc_editable;
1158
1159 return TRUE(!(0));
1160}
1161
1162static const guint forbidden_keyvals[] = {
1163 /* Navigation keys */
1164 CDK_KEY_Home0xff50,
1165 CDK_KEY_Left0xff51,
1166 CDK_KEY_Up0xff52,
1167 CDK_KEY_Right0xff53,
1168 CDK_KEY_Down0xff54,
1169 CDK_KEY_Page_Up0xff55,
1170 CDK_KEY_Page_Down0xff56,
1171 CDK_KEY_End0xff57,
1172 CDK_KEY_Tab0xff09,
1173
1174 /* Return */
1175 CDK_KEY_KP_Enter0xff8d,
1176 CDK_KEY_Return0xff0d,
1177
1178 CDK_KEY_space0x020,
1179 CDK_KEY_Mode_switch0xff7e
1180};
1181
1182static gboolean keyval_is_forbidden(guint keyval)
1183{
1184 guint i;
1185
1186 for (i = 0; i < G_N_ELEMENTS(forbidden_keyvals)(sizeof (forbidden_keyvals) / sizeof ((forbidden_keyvals)[0])
)
; i++)
1187 {
1188 if (keyval == forbidden_keyvals[i])
1189 {
1190 return TRUE(!(0));
1191 }
1192 }
1193
1194 return FALSE(0);
1195}
1196
1197static void show_error(CtkWindow* parent, GError* err)
1198{
1199 CtkWidget *dialog;
1200
1201 dialog = ctk_message_dialog_new (parent,
1202 CTK_DIALOG_DESTROY_WITH_PARENT | CTK_DIALOG_MODAL,
1203 CTK_MESSAGE_WARNING,
1204 CTK_BUTTONS_OK,
1205 _("Error saving the new shortcut")gettext ("Error saving the new shortcut"));
1206
1207 ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ())
)))))
,
1208 "%s", err->message);
1209 ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
1210 ctk_widget_destroy (dialog);
1211}
1212
1213static void accel_edited_callback(CtkCellRendererText* cell, const char* path_string, guint keyval, EggVirtualModifierType mask, guint keycode, gpointer data)
1214{
1215 CtkTreeView* view = (CtkTreeView*) data;
1216 CtkTreeModel* model;
1217 CtkTreePath* path = ctk_tree_path_new_from_string (path_string);
1218 CtkTreeIter iter;
1219 KeyEntry* key_entry, tmp_key;
1220 char* str;
1221
1222 block_accels = FALSE(0);
1223
1224 model = ctk_tree_view_get_model (view);
1225 ctk_tree_model_get_iter (model, &iter, path);
1226 ctk_tree_path_free (path);
1227 ctk_tree_model_get (model, &iter,
1228 KEYENTRY_COLUMN, &key_entry,
1229 -1);
1230
1231 /* sanity check */
1232 if (key_entry == NULL((void*)0))
1233 {
1234 return;
1235 }
1236
1237 /* CapsLock isn't supported as a keybinding modifier, so keep it from confusing us */
1238 mask &= ~EGG_VIRTUAL_LOCK_MASK;
1239
1240 tmp_key.model = model;
1241 tmp_key.keyval = keyval;
1242 tmp_key.keycode = keycode;
1243 tmp_key.mask = mask;
1244 tmp_key.settings = key_entry->settings;
1245 tmp_key.gsettings_key = key_entry->gsettings_key;
1246 tmp_key.description = NULL((void*)0);
1247 tmp_key.editable = TRUE(!(0)); /* kludge to stuff in a return flag */
1248
1249 if (keyval != 0 || keycode != 0) /* any number of keys can be disabled */
1250 {
1251 ctk_tree_model_foreach(model, (CtkTreeModelForeachFunc) cb_check_for_uniqueness, &tmp_key);
1252 }
1253
1254 /* Check for unmodified keys */
1255 if (tmp_key.mask == 0 && tmp_key.keycode != 0)
1256 {
1257 if ((tmp_key.keyval >= CDK_KEY_a0x061 && tmp_key.keyval <= CDK_KEY_z0x07a)
1258 || (tmp_key.keyval >= CDK_KEY_A0x041 && tmp_key.keyval <= CDK_KEY_Z0x05a)
1259 || (tmp_key.keyval >= CDK_KEY_00x030 && tmp_key.keyval <= CDK_KEY_90x039)
1260 || (tmp_key.keyval >= CDK_KEY_kana_fullstop0x4a1 && tmp_key.keyval <= CDK_KEY_semivoicedsound0x4df)
1261 || (tmp_key.keyval >= CDK_KEY_Arabic_comma0x5ac && tmp_key.keyval <= CDK_KEY_Arabic_sukun0x5f2)
1262 || (tmp_key.keyval >= CDK_KEY_Serbian_dje0x6a1 && tmp_key.keyval <= CDK_KEY_Cyrillic_HARDSIGN0x6ff)
1263 || (tmp_key.keyval >= CDK_KEY_Greek_ALPHAaccent0x7a1 && tmp_key.keyval <= CDK_KEY_Greek_omega0x7f9)
1264 || (tmp_key.keyval >= CDK_KEY_hebrew_doublelowline0xcdf && tmp_key.keyval <= CDK_KEY_hebrew_taf0xcfa)
1265 || (tmp_key.keyval >= CDK_KEY_Thai_kokai0xda1 && tmp_key.keyval <= CDK_KEY_Thai_lekkao0xdf9)
1266 || (tmp_key.keyval >= CDK_KEY_Hangul0xff31 && tmp_key.keyval <= CDK_KEY_Hangul_Special0xff3f)
1267 || (tmp_key.keyval >= CDK_KEY_Hangul_Kiyeog0xea1 && tmp_key.keyval <= CDK_KEY_Hangul_J_YeorinHieuh0xefa)
1268 || keyval_is_forbidden (tmp_key.keyval))
1269 {
1270
1271 CtkWidget *dialog;
1272 char *name;
1273
1274 name = binding_name (keyval, keycode, mask, TRUE(!(0)));
1275
1276 dialog = ctk_message_dialog_new (
1277 CTK_WINDOW (ctk_widget_get_toplevel (CTK_WIDGET (view)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), ((ctk_widget_get_type ()))))))))
), ((ctk_window_get_type ()))))))
,
1278 CTK_DIALOG_DESTROY_WITH_PARENT | CTK_DIALOG_MODAL,
1279 CTK_MESSAGE_WARNING,
1280 CTK_BUTTONS_CANCEL,
1281 _("The shortcut \"%s\" cannot be used because it will become impossible to type using this key.\n"gettext ("The shortcut \"%s\" cannot be used because it will become impossible to type using this key.\n"
"Please try with a key such as Control, Alt or Shift at the same time."
)
1282 "Please try with a key such as Control, Alt or Shift at the same time.")gettext ("The shortcut \"%s\" cannot be used because it will become impossible to type using this key.\n"
"Please try with a key such as Control, Alt or Shift at the same time."
)
,
1283 name);
1284
1285 g_free (name);
1286 ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
1287 ctk_widget_destroy (dialog);
1288
1289 /* set it back to its previous value. */
1290 egg_cell_renderer_keys_set_accelerator(
1291 EGG_CELL_RENDERER_KEYS(cell)((((EggCellRendererKeys*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((cell)), ((egg_cell_renderer_keys_get_type
()))))))
,
1292 key_entry->keyval,
1293 key_entry->keycode,
1294 key_entry->mask);
1295 return;
1296 }
1297 }
1298
1299 /* flag to see if the new accelerator was in use by something */
1300 if (!tmp_key.editable)
1301 {
1302 CtkWidget* dialog;
1303 char* name;
1304 int response;
1305
1306 name = binding_name(keyval, keycode, mask, TRUE(!(0)));
1307
1308 dialog = ctk_message_dialog_new(
1309 CTK_WINDOW(ctk_widget_get_toplevel(CTK_WIDGET(view)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel(((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((view)), ((ctk_widget_get_type ()))))))))
), ((ctk_window_get_type ()))))))
,
1310 CTK_DIALOG_DESTROY_WITH_PARENT | CTK_DIALOG_MODAL,
1311 CTK_MESSAGE_WARNING,
1312 CTK_BUTTONS_CANCEL,
1313 _("The shortcut \"%s\" is already used for\n\"%s\"")gettext ("The shortcut \"%s\" is already used for\n\"%s\""),
1314 name,
1315 tmp_key.description ? tmp_key.description : tmp_key.gsettings_key);
1316 g_free (name);
1317
1318 ctk_message_dialog_format_secondary_text (
1319 CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ())
)))))
,
1320 _("If you reassign the shortcut to \"%s\", the \"%s\" shortcut "gettext ("If you reassign the shortcut to \"%s\", the \"%s\" shortcut "
"will be disabled.")
1321 "will be disabled.")gettext ("If you reassign the shortcut to \"%s\", the \"%s\" shortcut "
"will be disabled.")
,
1322 key_entry->description ? key_entry->description : key_entry->gsettings_key,
1323 tmp_key.description ? tmp_key.description : tmp_key.gsettings_key);
1324
1325 ctk_dialog_add_button(CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, _("_Reassign")gettext ("_Reassign"), CTK_RESPONSE_ACCEPT);
1326
1327 ctk_dialog_set_default_response(CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, CTK_RESPONSE_ACCEPT);
1328
1329 response = ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
1330 ctk_widget_destroy (dialog);
1331
1332 if (response == CTK_RESPONSE_ACCEPT)
1333 {
1334 g_settings_set_string (tmp_key.settings, tmp_key.gsettings_key, "disabled");
1335
1336 str = binding_name (keyval, keycode, mask, FALSE(0));
1337 g_settings_set_string (key_entry->settings, key_entry->gsettings_key, str);
1338
1339 g_free (str);
1340 }
1341 else
1342 {
1343 /* set it back to its previous value. */
1344 egg_cell_renderer_keys_set_accelerator(
1345 EGG_CELL_RENDERER_KEYS(cell)((((EggCellRendererKeys*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((cell)), ((egg_cell_renderer_keys_get_type
()))))))
,
1346 key_entry->keyval,
1347 key_entry->keycode,
1348 key_entry->mask);
1349 }
1350
1351 return;
1352 }
1353
1354 str = binding_name (keyval, keycode, mask, FALSE(0));
1355
1356 g_settings_set_string(
1357 key_entry->settings,
1358 key_entry->gsettings_key,
1359 str);
1360
1361 g_free (str);
1362
1363}
1364
1365static void
1366accel_cleared_callback (CtkCellRendererText *cell,
1367 const char *path_string,
1368 gpointer data)
1369{
1370 CtkTreeView *view = (CtkTreeView *) data;
1371 CtkTreePath *path = ctk_tree_path_new_from_string (path_string);
1372 KeyEntry *key_entry;
1373 CtkTreeIter iter;
1374 CtkTreeModel *model;
1375
1376 block_accels = FALSE(0);
1377
1378 model = ctk_tree_view_get_model (view);
1379 ctk_tree_model_get_iter (model, &iter, path);
1380 ctk_tree_path_free (path);
1381 ctk_tree_model_get (model, &iter,
1382 KEYENTRY_COLUMN, &key_entry,
1383 -1);
1384
1385 /* sanity check */
1386 if (key_entry == NULL((void*)0))
1387 return;
1388
1389 /* Unset the key */
1390 g_settings_set_string (key_entry->settings,
1391 key_entry->gsettings_key,
1392 "disabled");
1393}
1394
1395static void
1396description_edited_callback (CtkCellRendererText *renderer,
1397 gchar *path_string,
1398 gchar *new_text,
1399 gpointer user_data)
1400{
1401 CtkTreeView *view = CTK_TREE_VIEW (user_data)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((user_data)), ((ctk_tree_view_get_type ()))))))
;
1402 CtkTreeModel *model;
1403 CtkTreePath *path = ctk_tree_path_new_from_string (path_string);
1404 CtkTreeIter iter;
1405 KeyEntry *key_entry;
1406
1407 model = ctk_tree_view_get_model (view);
1408 ctk_tree_model_get_iter (model, &iter, path);
1409 ctk_tree_path_free (path);
1410
1411 ctk_tree_model_get (model, &iter,
1412 KEYENTRY_COLUMN, &key_entry,
1413 -1);
1414
1415 /* sanity check */
1416 if (key_entry == NULL((void*)0) || key_entry->desc_gsettings_key == NULL((void*)0))
1417 return;
1418
1419 if (!g_settings_set_string (key_entry->settings, key_entry->desc_gsettings_key, new_text))
1420 key_entry->desc_editable = FALSE(0);
1421}
1422
1423
1424typedef struct
1425{
1426 CtkTreeView *tree_view;
1427 CtkTreePath *path;
1428 CtkTreeViewColumn *column;
1429} IdleData;
1430
1431static gboolean
1432real_start_editing_cb (IdleData *idle_data)
1433{
1434 ctk_widget_grab_focus (CTK_WIDGET (idle_data->tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((idle_data->tree_view)), ((ctk_widget_get_type ())))))
)
);
1435 ctk_tree_view_set_cursor (idle_data->tree_view,
1436 idle_data->path,
1437 idle_data->column,
1438 TRUE(!(0)));
1439 ctk_tree_path_free (idle_data->path);
1440 g_free (idle_data);
1441 return FALSE(0);
1442}
1443
1444static gboolean
1445edit_custom_shortcut (KeyEntry *key)
1446{
1447 gint result;
1448 const gchar *text;
1449 gboolean ret;
1450
1451 ctk_entry_set_text (CTK_ENTRY (custom_shortcut_name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_name_entry)), ((ctk_entry_get_type ())))
)))
, key->description ? key->description : "");
1452 ctk_widget_set_sensitive (custom_shortcut_name_entry, key->desc_editable);
1453 ctk_widget_grab_focus (custom_shortcut_name_entry);
1454 ctk_entry_set_text (CTK_ENTRY (custom_shortcut_command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_command_entry)), ((ctk_entry_get_type ()
))))))
, key->command ? key->command : "");
1455 ctk_widget_set_sensitive (custom_shortcut_command_entry, key->cmd_editable);
1456
1457 ctk_window_present (CTK_WINDOW (custom_shortcut_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_dialog)), ((ctk_window_get_type ()))))))
);
1458 result = ctk_dialog_run (CTK_DIALOG (custom_shortcut_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_dialog)), ((ctk_dialog_get_type ()))))))
);
1459 switch (result)
1460 {
1461 case CTK_RESPONSE_OK:
1462 text = ctk_entry_get_text (CTK_ENTRY (custom_shortcut_name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_name_entry)), ((ctk_entry_get_type ())))
)))
);
1463 g_free (key->description);
1464 key->description = g_strdup (text)g_strdup_inline (text);
1465 text = ctk_entry_get_text (CTK_ENTRY (custom_shortcut_command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_command_entry)), ((ctk_entry_get_type ()
))))))
);
1466 g_free (key->command);
1467 key->command = g_strdup (text)g_strdup_inline (text);
1468 ret = TRUE(!(0));
1469 break;
1470 default:
1471 ret = FALSE(0);
1472 break;
1473 }
1474
1475 ctk_widget_hide (custom_shortcut_dialog);
1476
1477 return ret;
1478}
1479
1480static gboolean
1481remove_custom_shortcut (CtkTreeModel *model, CtkTreeIter *iter)
1482{
1483 CtkTreeIter parent;
1484 KeyEntry *key;
1485
1486 ctk_tree_model_get (model, iter,
1487 KEYENTRY_COLUMN, &key,
1488 -1);
1489
1490 /* not a custom shortcut */
1491 if (key->command == NULL((void*)0))
1492 return FALSE(0);
1493
1494 g_signal_handler_disconnect (key->settings, key->gsettings_cnxn);
1495 if (key->gsettings_cnxn_desc != 0)
1496 g_signal_handler_disconnect (key->settings, key->gsettings_cnxn_desc);
1497 if (key->gsettings_cnxn_cmd != 0)
1498 g_signal_handler_disconnect (key->settings, key->gsettings_cnxn_cmd);
1499
1500 dconf_util_recursive_reset (key->gsettings_path, NULL((void*)0));
1501 g_object_unref (key->settings);
1502
1503 g_free (key->gsettings_path);
1504 g_free (key->gsettings_key);
1505 g_free (key->description);
1506 g_free (key->desc_gsettings_key);
1507 g_free (key->command);
1508 g_free (key->cmd_gsettings_key);
1509 g_free (key);
1510
1511 ctk_tree_model_iter_parent (model, &parent, iter);
1512 ctk_tree_store_remove (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, iter);
1513 if (!ctk_tree_model_iter_has_child (model, &parent))
1514 ctk_tree_store_remove (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &parent);
1515
1516 return TRUE(!(0));
1517}
1518
1519static void
1520update_custom_shortcut (CtkTreeModel *model, CtkTreeIter *iter)
1521{
1522 KeyEntry *key;
1523
1524 ctk_tree_model_get (model, iter,
1525 KEYENTRY_COLUMN, &key,
1526 -1);
1527
1528 edit_custom_shortcut (key);
1529 if (key->command == NULL((void*)0) || key->command[0] == '\0')
1530 {
1531 remove_custom_shortcut (model, iter);
1532 }
1533 else
1534 {
1535 ctk_tree_store_set (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, iter,
1536 KEYENTRY_COLUMN, key, -1);
1537 if (key->description != NULL((void*)0))
1538 g_settings_set_string (key->settings, key->desc_gsettings_key, key->description);
1539 else
1540 g_settings_reset (key->settings, key->desc_gsettings_key);
1541 g_settings_set_string (key->settings, key->cmd_gsettings_key, key->command);
1542 }
1543}
1544
1545static gchar *
1546find_free_gsettings_path (GError **error)
1547{
1548 gchar **existing_dirs;
1549 gchar *dir = NULL((void*)0);
1550 gchar *fulldir = NULL((void*)0);
1551 int i;
1552 int j;
1553 gboolean found;
1554
1555 existing_dirs = dconf_util_list_subdirs (GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/", FALSE(0));
1556
1557 for (i = 0; i < MAX_CUSTOM_SHORTCUTS1000; i++)
1558 {
1559 found = TRUE(!(0));
1560 dir = g_strdup_printf ("custom%d/", i);
1561 for (j = 0; existing_dirs[j] != NULL((void*)0); j++)
1562 if (!g_strcmp0(dir, existing_dirs[j]))
1563 {
1564 found = FALSE(0);
1565 g_free (dir);
1566 break;
1567 }
1568 if (found)
1569 break;
1570 }
1571 g_strfreev (existing_dirs);
1572
1573 if (i == MAX_CUSTOM_SHORTCUTS1000)
1574 {
1575 g_free (dir);
1576 dir = NULL((void*)0);
1577 g_set_error_literal (error,
1578 g_quark_from_string ("Keyboard Shortcuts"),
1579 0,
1580 _("Too many custom shortcuts")gettext ("Too many custom shortcuts"));
1581 }
1582
1583 fulldir = g_strdup_printf ("%s%s", GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/", dir);
1584 g_free (dir);
1585 return fulldir;
1586}
1587
1588static void
1589add_custom_shortcut (CtkTreeView *tree_view,
1590 CtkTreeModel *model)
1591{
1592 KeyEntry *key_entry;
1593 CtkTreeIter iter;
1594 CtkTreeIter parent_iter;
1595 CtkTreePath *path;
1596 gchar *dir;
1597 GError *error;
1598
1599 error = NULL((void*)0);
1600 dir = find_free_gsettings_path (&error);
1601 if (dir == NULL((void*)0))
1602 {
1603 show_error (CTK_WINDOW (ctk_widget_get_toplevel (CTK_WIDGET (tree_view)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((tree_view)), ((ctk_widget_get_type ())))
)))))), ((ctk_window_get_type ()))))))
, error);
1604
1605 g_error_free (error);
1606 return;
1607 }
1608
1609 key_entry = g_new0 (KeyEntry, 1)((KeyEntry *) g_malloc0_n ((1), sizeof (KeyEntry)));
1610 key_entry->gsettings_path = g_strdup(dir)g_strdup_inline (dir);
1611 key_entry->gsettings_key = g_strdup("binding")g_strdup_inline ("binding");
1612 key_entry->editable = TRUE(!(0));
1613 key_entry->model = model;
1614 key_entry->desc_gsettings_key = g_strdup("name")g_strdup_inline ("name");
1615 key_entry->description = g_strdup ("")g_strdup_inline ("");
1616 key_entry->desc_editable = TRUE(!(0));
1617 key_entry->cmd_gsettings_key = g_strdup("action")g_strdup_inline ("action");
1618 key_entry->command = g_strdup ("")g_strdup_inline ("");
1619 key_entry->cmd_editable = TRUE(!(0));
1620 g_free (dir);
1621
1622 if (edit_custom_shortcut (key_entry) &&
1623 key_entry->command && key_entry->command[0])
1624 {
1625 find_section (model, &iter, _("Custom Shortcuts")gettext ("Custom Shortcuts"));
1626 parent_iter = iter;
1627 ctk_tree_store_append (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &iter, &parent_iter);
1628 ctk_tree_store_set (CTK_TREE_STORE (model)((((CtkTreeStore*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((model)), ((ctk_tree_store_get_type ()))))))
, &iter, KEYENTRY_COLUMN, key_entry, -1);
1629
1630 /* store in gsettings */
1631 key_entry->settings = g_settings_new_with_path (CUSTOM_KEYBINDING_SCHEMA"org.cafe.control-center.keybinding", key_entry->gsettings_path);
1632 g_settings_set_string (key_entry->settings, key_entry->gsettings_key, "disabled");
1633 g_settings_set_string (key_entry->settings, key_entry->desc_gsettings_key, key_entry->description);
1634 g_settings_set_string (key_entry->settings, key_entry->cmd_gsettings_key, key_entry->command);
1635
1636 /* add gsettings watches */
1637 key_entry->gsettings_cnxn_desc = g_signal_connect (key_entry->settings,g_signal_connect_data ((key_entry->settings), ("changed::name"
), (((GCallback) (keybinding_description_changed))), (key_entry
), ((void*)0), (GConnectFlags) 0)
1638 "changed::name",g_signal_connect_data ((key_entry->settings), ("changed::name"
), (((GCallback) (keybinding_description_changed))), (key_entry
), ((void*)0), (GConnectFlags) 0)
1639 G_CALLBACK (keybinding_description_changed),g_signal_connect_data ((key_entry->settings), ("changed::name"
), (((GCallback) (keybinding_description_changed))), (key_entry
), ((void*)0), (GConnectFlags) 0)
1640 key_entry)g_signal_connect_data ((key_entry->settings), ("changed::name"
), (((GCallback) (keybinding_description_changed))), (key_entry
), ((void*)0), (GConnectFlags) 0)
;
1641 key_entry->gsettings_cnxn_cmd = g_signal_connect (key_entry->settings,g_signal_connect_data ((key_entry->settings), ("changed::action"
), (((GCallback) (keybinding_command_changed))), (key_entry),
((void*)0), (GConnectFlags) 0)
1642 "changed::action",g_signal_connect_data ((key_entry->settings), ("changed::action"
), (((GCallback) (keybinding_command_changed))), (key_entry),
((void*)0), (GConnectFlags) 0)
1643 G_CALLBACK (keybinding_command_changed),g_signal_connect_data ((key_entry->settings), ("changed::action"
), (((GCallback) (keybinding_command_changed))), (key_entry),
((void*)0), (GConnectFlags) 0)
1644 key_entry)g_signal_connect_data ((key_entry->settings), ("changed::action"
), (((GCallback) (keybinding_command_changed))), (key_entry),
((void*)0), (GConnectFlags) 0)
;
1645 key_entry->gsettings_cnxn = g_signal_connect (key_entry->settings,g_signal_connect_data ((key_entry->settings), ("changed::binding"
), (((GCallback) (keybinding_key_changed))), (key_entry), ((void
*)0), (GConnectFlags) 0)
1646 "changed::binding",g_signal_connect_data ((key_entry->settings), ("changed::binding"
), (((GCallback) (keybinding_key_changed))), (key_entry), ((void
*)0), (GConnectFlags) 0)
1647 G_CALLBACK (keybinding_key_changed),g_signal_connect_data ((key_entry->settings), ("changed::binding"
), (((GCallback) (keybinding_key_changed))), (key_entry), ((void
*)0), (GConnectFlags) 0)
1648 key_entry)g_signal_connect_data ((key_entry->settings), ("changed::binding"
), (((GCallback) (keybinding_key_changed))), (key_entry), ((void
*)0), (GConnectFlags) 0)
;
1649
1650 /* make the new shortcut visible */
1651 path = ctk_tree_model_get_path (model, &iter);
1652 ctk_tree_view_expand_to_path (tree_view, path);
1653 ctk_tree_view_scroll_to_cell (tree_view, path, NULL((void*)0), FALSE(0), 0, 0);
1654 ctk_tree_path_free (path);
1655 }
1656 else
1657 {
1658 g_free (key_entry->gsettings_path);
1659 g_free (key_entry->gsettings_key);
1660 g_free (key_entry->description);
1661 g_free (key_entry->desc_gsettings_key);
1662 g_free (key_entry->command);
1663 g_free (key_entry->cmd_gsettings_key);
1664 g_free (key_entry);
1665 }
1666}
1667
1668static void
1669start_editing_kb_cb (CtkTreeView *treeview,
1670 CtkTreePath *path,
1671 CtkTreeViewColumn *column,
1672 gpointer user_data)
1673{
1674 CtkTreeModel *model;
1675 CtkTreeIter iter;
1676 KeyEntry *key;
1677
1678 model = ctk_tree_view_get_model (treeview);
1679 ctk_tree_model_get_iter (model, &iter, path);
1680 ctk_tree_model_get (model, &iter,
1681 KEYENTRY_COLUMN, &key,
1682 -1);
1683
1684 if (key == NULL((void*)0))
1685 {
1686 /* This is a section heading - expand or collapse */
1687 if (ctk_tree_view_row_expanded (treeview, path))
1688 ctk_tree_view_collapse_row (treeview, path);
1689 else
1690 ctk_tree_view_expand_row (treeview, path, FALSE(0));
1691 return;
1692 }
1693
1694 /* if only the accel can be edited on the selected row
1695 * always select the accel column */
1696 if (key->desc_editable &&
1697 column == ctk_tree_view_get_column (treeview, 0))
1698 {
1699 ctk_widget_grab_focus (CTK_WIDGET (treeview)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((treeview)), ((ctk_widget_get_type ()))))))
);
1700 ctk_tree_view_set_cursor (treeview, path,
1701 ctk_tree_view_get_column (treeview, 0),
1702 FALSE(0));
1703 update_custom_shortcut (model, &iter);
1704 }
1705 else
1706 {
1707 ctk_widget_grab_focus (CTK_WIDGET (treeview)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((treeview)), ((ctk_widget_get_type ()))))))
);
1708 ctk_tree_view_set_cursor (treeview,
1709 path,
1710 ctk_tree_view_get_column (treeview, 1),
1711 TRUE(!(0)));
1712 }
1713}
1714
1715static gboolean
1716start_editing_cb (CtkTreeView *tree_view,
1717 CdkEventButton *event,
1718 gpointer user_data)
1719{
1720 CtkTreePath *path;
1721 CtkTreeViewColumn *column;
1722
1723 if ((event->window != ctk_tree_view_get_bin_window (tree_view)) ||
1724 (event->type != CDK_2BUTTON_PRESS))
1725 return FALSE(0);
1726
1727 if (ctk_tree_view_get_path_at_pos (tree_view,
1728 (gint) event->x,
1729 (gint) event->y,
1730 &path, &column,
1731 NULL((void*)0), NULL((void*)0)))
1732 {
1733 IdleData *idle_data;
1734 CtkTreeModel *model;
1735 CtkTreeIter iter;
1736 KeyEntry *key;
1737
1738 if (ctk_tree_path_get_depth (path) == 1)
1739 {
1740 ctk_tree_path_free (path);
1741 return FALSE(0);
1742 }
1743
1744 model = ctk_tree_view_get_model (tree_view);
1745 ctk_tree_model_get_iter (model, &iter, path);
1746 ctk_tree_model_get (model, &iter,
1747 KEYENTRY_COLUMN, &key,
1748 -1);
1749
1750 /* if only the accel can be edited on the selected row
1751 * always select the accel column */
1752 if (key->desc_editable &&
1753 column == ctk_tree_view_get_column (tree_view, 0))
1754 {
1755 ctk_widget_grab_focus (CTK_WIDGET (tree_view)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((tree_view)), ((ctk_widget_get_type ()))))))
);
1756 ctk_tree_view_set_cursor (tree_view, path,
1757 ctk_tree_view_get_column (tree_view, 0),
1758 FALSE(0));
1759 update_custom_shortcut (model, &iter);
1760 }
1761 else
1762 {
1763 idle_data = g_new (IdleData, 1)((IdleData *) g_malloc_n ((1), sizeof (IdleData)));
1764 idle_data->tree_view = tree_view;
1765 idle_data->path = path;
1766 idle_data->column = key->desc_editable ? column :
1767 ctk_tree_view_get_column (tree_view, 1);
1768 g_idle_add ((GSourceFunc) real_start_editing_cb, idle_data);
1769 block_accels = TRUE(!(0));
1770 }
1771 g_signal_stop_emission_by_name (tree_view, "button_press_event");
1772 }
1773 return TRUE(!(0));
1774}
1775
1776/* this handler is used to keep accels from activating while the user
1777 * is assigning a new shortcut so that he won't accidentally trigger one
1778 * of the widgets */
1779static gboolean maybe_block_accels(CtkWidget* widget, CdkEventKey* event, gpointer user_data)
1780{
1781 if (block_accels)
1782 {
1783 return ctk_window_propagate_key_event(CTK_WINDOW(widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_window_get_type ()))))))
, event);
1784 }
1785
1786 return FALSE(0);
1787}
1788
1789static void
1790cb_dialog_response (CtkWidget *widget, gint response_id, gpointer data)
1791{
1792 CtkBuilder *builder = data;
1793 CtkTreeView *treeview;
1794 CtkTreeModel *model;
1795 CtkTreeSelection *selection;
1796 CtkTreeIter iter;
1797
1798 treeview = CTK_TREE_VIEW (ctk_builder_get_object (builder,((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
1799 "shortcut_treeview"))((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
;
1800 model = ctk_tree_view_get_model (treeview);
1801
1802 if (response_id == CTK_RESPONSE_HELP)
1803 {
1804 capplet_help (CTK_WINDOW (widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_window_get_type ()))))))
,
1805 "goscustdesk-39");
1806 }
1807 else if (response_id == RESPONSE_ADD0)
1808 {
1809 add_custom_shortcut (treeview, model);
1810 }
1811 else if (response_id == RESPONSE_REMOVE1)
1812 {
1813 selection = ctk_tree_view_get_selection (treeview);
1814 if (ctk_tree_selection_get_selected (selection, NULL((void*)0), &iter))
1815 {
1816 remove_custom_shortcut (model, &iter);
1817 }
1818 }
1819 else
1820 {
1821 clear_old_model (builder);
1822 ctk_main_quit ();
1823 }
1824}
1825
1826static void
1827selection_changed (CtkTreeSelection *selection, gpointer data)
1828{
1829 CtkWidget *button = data;
1830 CtkTreeModel *model;
1831 CtkTreeIter iter;
1832 KeyEntry *key;
1833 gboolean can_remove;
1834
1835 can_remove = FALSE(0);
1836 if (ctk_tree_selection_get_selected (selection, &model, &iter))
1837 {
1838 ctk_tree_model_get (model, &iter, KEYENTRY_COLUMN, &key, -1);
1839 if (key && key->command != NULL((void*)0) && key->editable)
1840 can_remove = TRUE(!(0));
1841 }
1842
1843 ctk_widget_set_sensitive (button, can_remove);
1844}
1845
1846static void
1847cb_app_dialog_response (CtkWidget *dialog, gint response_id, gpointer data)
1848{
1849 if (response_id == CTK_RESPONSE_OK)
1850 {
1851 GAppInfo *info;
1852 const gchar *custom_name;
1853
1854 info = ctk_app_chooser_get_app_info (CTK_APP_CHOOSER (dialog)((((CtkAppChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_app_chooser_get_type ()))))))
);
1855
1856 ctk_entry_set_text (CTK_ENTRY (custom_shortcut_command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_command_entry)), ((ctk_entry_get_type ()
))))))
,
1857 g_app_info_get_executable (info));
1858 /* if name isn't set yet, use the associated one */
1859 custom_name = ctk_entry_get_text (CTK_ENTRY (custom_shortcut_name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_name_entry)), ((ctk_entry_get_type ())))
)))
);
1860 if (! custom_name || custom_name[0] == '\0')
1861 ctk_entry_set_text (CTK_ENTRY (custom_shortcut_name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_name_entry)), ((ctk_entry_get_type ())))
)))
,
1862 g_app_info_get_display_name (info));
1863
1864 g_object_unref (info);
1865 }
1866
1867 ctk_widget_hide (dialog);
1868}
1869
1870static void
1871setup_dialog (CtkBuilder *builder, GSettings *croma_settings)
1872{
1873 CtkCellRenderer *renderer;
1874 CtkTreeViewColumn *column;
1875 CtkWidget *widget;
1876 CtkTreeView *treeview;
1877 CtkTreeSelection *selection;
1878 CtkWidget *button;
1879
1880 treeview = CTK_TREE_VIEW (ctk_builder_get_object (builder,((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
1881 "shortcut_treeview"))((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "shortcut_treeview"))),
((ctk_tree_view_get_type ()))))))
;
1882
1883 g_signal_connect (treeview, "button_press_event",g_signal_connect_data ((treeview), ("button_press_event"), ((
(GCallback) (start_editing_cb))), (builder), ((void*)0), (GConnectFlags
) 0)
1884 G_CALLBACK (start_editing_cb), builder)g_signal_connect_data ((treeview), ("button_press_event"), ((
(GCallback) (start_editing_cb))), (builder), ((void*)0), (GConnectFlags
) 0)
;
1885 g_signal_connect (treeview, "row-activated",g_signal_connect_data ((treeview), ("row-activated"), (((GCallback
) (start_editing_kb_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1886 G_CALLBACK (start_editing_kb_cb), NULL)g_signal_connect_data ((treeview), ("row-activated"), (((GCallback
) (start_editing_kb_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1887
1888 renderer = ctk_cell_renderer_text_new ();
1889
1890 g_signal_connect (renderer, "edited",g_signal_connect_data ((renderer), ("edited"), (((GCallback) (
description_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1891 G_CALLBACK (description_edited_callback),g_signal_connect_data ((renderer), ("edited"), (((GCallback) (
description_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1892 treeview)g_signal_connect_data ((renderer), ("edited"), (((GCallback) (
description_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
;
1893
1894 column = ctk_tree_view_column_new_with_attributes (_("Action")gettext ("Action"),
1895 renderer,
1896 "text", DESCRIPTION_COLUMN,
1897 NULL((void*)0));
1898 ctk_tree_view_column_set_cell_data_func (column, renderer, description_set_func, NULL((void*)0), NULL((void*)0));
1899 ctk_tree_view_column_set_resizable (column, FALSE(0));
1900
1901 ctk_tree_view_append_column (treeview, column);
1902 ctk_tree_view_column_set_sort_column_id (column, DESCRIPTION_COLUMN);
1903
1904 renderer = (CtkCellRenderer *) g_object_new (EGG_TYPE_CELL_RENDERER_KEYS(egg_cell_renderer_keys_get_type ()),
1905 "accel_mode", EGG_CELL_RENDERER_KEYS_MODE_X,
1906 NULL((void*)0));
1907
1908 g_signal_connect (renderer, "accel_edited",g_signal_connect_data ((renderer), ("accel_edited"), (((GCallback
) (accel_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1909 G_CALLBACK (accel_edited_callback),g_signal_connect_data ((renderer), ("accel_edited"), (((GCallback
) (accel_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1910 treeview)g_signal_connect_data ((renderer), ("accel_edited"), (((GCallback
) (accel_edited_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
;
1911
1912 g_signal_connect (renderer, "accel_cleared",g_signal_connect_data ((renderer), ("accel_cleared"), (((GCallback
) (accel_cleared_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1913 G_CALLBACK (accel_cleared_callback),g_signal_connect_data ((renderer), ("accel_cleared"), (((GCallback
) (accel_cleared_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
1914 treeview)g_signal_connect_data ((renderer), ("accel_cleared"), (((GCallback
) (accel_cleared_callback))), (treeview), ((void*)0), (GConnectFlags
) 0)
;
1915
1916 column = ctk_tree_view_column_new_with_attributes (_("Shortcut")gettext ("Shortcut"), renderer, NULL((void*)0));
1917 ctk_tree_view_column_set_cell_data_func (column, renderer, accel_set_func, NULL((void*)0), NULL((void*)0));
1918 ctk_tree_view_column_set_resizable (column, FALSE(0));
1919
1920 ctk_tree_view_append_column (treeview, column);
1921 ctk_tree_view_column_set_sort_column_id (column, KEYENTRY_COLUMN);
1922
1923 g_signal_connect (croma_settings,g_signal_connect_data ((croma_settings), ("changed::num-workspaces"
), (((GCallback) (key_entry_controlling_key_changed))), (builder
), ((void*)0), (GConnectFlags) 0)
1924 "changed::num-workspaces",g_signal_connect_data ((croma_settings), ("changed::num-workspaces"
), (((GCallback) (key_entry_controlling_key_changed))), (builder
), ((void*)0), (GConnectFlags) 0)
1925 G_CALLBACK (key_entry_controlling_key_changed),g_signal_connect_data ((croma_settings), ("changed::num-workspaces"
), (((GCallback) (key_entry_controlling_key_changed))), (builder
), ((void*)0), (GConnectFlags) 0)
1926 builder)g_signal_connect_data ((croma_settings), ("changed::num-workspaces"
), (((GCallback) (key_entry_controlling_key_changed))), (builder
), ((void*)0), (GConnectFlags) 0)
;
1927
1928 /* set up the dialog */
1929 reload_key_entries (builder);
1930
1931 widget = _ctk_builder_get_widget (builder, "cafe-keybinding-dialog");
1932 ctk_window_set_default_size (CTK_WINDOW (widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_window_get_type ()))))))
, 400, 500);
1933 widget = _ctk_builder_get_widget (builder, "label-suggest");
1934 ctk_label_set_line_wrap (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
, TRUE(!(0)));
1935 ctk_label_set_max_width_chars (CTK_LABEL (widget)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_label_get_type ()))))))
, 60);
1936
1937 widget = _ctk_builder_get_widget (builder, "cafe-keybinding-dialog");
1938 capplet_set_icon (widget, "preferences-desktop-keyboard-shortcuts");
1939 ctk_widget_show (widget);
1940
1941 g_signal_connect (widget, "key_press_event", G_CALLBACK (maybe_block_accels), NULL)g_signal_connect_data ((widget), ("key_press_event"), (((GCallback
) (maybe_block_accels))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1942 g_signal_connect (widget, "response", G_CALLBACK (cb_dialog_response), builder)g_signal_connect_data ((widget), ("response"), (((GCallback) (
cb_dialog_response))), (builder), ((void*)0), (GConnectFlags)
0)
;
1943
1944 selection = ctk_tree_view_get_selection (CTK_TREE_VIEW (treeview)((((CtkTreeView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((treeview)), ((ctk_tree_view_get_type ()))))))
);
1945 g_signal_connect (selection, "changed",g_signal_connect_data ((selection), ("changed"), (((GCallback
) (selection_changed))), (_ctk_builder_get_widget (builder, "remove-button"
)), ((void*)0), (GConnectFlags) 0)
1946 G_CALLBACK (selection_changed),g_signal_connect_data ((selection), ("changed"), (((GCallback
) (selection_changed))), (_ctk_builder_get_widget (builder, "remove-button"
)), ((void*)0), (GConnectFlags) 0)
1947 _ctk_builder_get_widget (builder, "remove-button"))g_signal_connect_data ((selection), ("changed"), (((GCallback
) (selection_changed))), (_ctk_builder_get_widget (builder, "remove-button"
)), ((void*)0), (GConnectFlags) 0)
;
1948
1949 /* setup the custom shortcut dialog */
1950 custom_shortcut_dialog = _ctk_builder_get_widget (builder,
1951 "custom-shortcut-dialog");
1952 custom_shortcut_name_entry = _ctk_builder_get_widget (builder,
1953 "custom-shortcut-name-entry");
1954 custom_shortcut_command_entry = _ctk_builder_get_widget (builder,
1955 "custom-shortcut-command-entry");
1956 ctk_dialog_set_default_response (CTK_DIALOG (custom_shortcut_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_dialog)), ((ctk_dialog_get_type ()))))))
,
1957 CTK_RESPONSE_OK);
1958 ctk_window_set_transient_for (CTK_WINDOW (custom_shortcut_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((custom_shortcut_dialog)), ((ctk_window_get_type ()))))))
,
1959 CTK_WINDOW (widget)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_window_get_type ()))))))
);
1960 button = _ctk_builder_get_widget (builder, "custom-shortcut-command-button");
1961 widget = _ctk_builder_get_widget (builder, "custom-shortcut-application-dialog");
1962 g_signal_connect_swapped (button, "clicked", G_CALLBACK (ctk_dialog_run), widget)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_dialog_run))), (widget), ((void*)0), G_CONNECT_SWAPPED)
;
1963 g_signal_connect (widget, "response", G_CALLBACK (cb_app_dialog_response), NULL)g_signal_connect_data ((widget), ("response"), (((GCallback) (
cb_app_dialog_response))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1964 widget = ctk_app_chooser_dialog_get_widget (CTK_APP_CHOOSER_DIALOG (widget)((((CtkAppChooserDialog*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_app_chooser_dialog_get_type
()))))))
);
1965 ctk_app_chooser_widget_set_show_all (CTK_APP_CHOOSER_WIDGET (widget)((((CtkAppChooserWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((widget)), ((ctk_app_chooser_widget_get_type
()))))))
, TRUE(!(0)));
1966}
1967
1968static void
1969on_window_manager_change (const char *wm_name, CtkBuilder *builder)
1970{
1971 reload_key_entries (builder);
1972}
1973
1974int
1975main (int argc, char *argv[])
1976{
1977 CtkBuilder *builder;
1978 GSettings *croma_settings;
1979
1980 capplet_init (NULL((void*)0), &argc, &argv);
1981
1982 activate_settings_daemon ();
1983
1984 builder = create_builder ();
1985
1986 if (!builder) /* Warning was already printed to console */
1987 exit (EXIT_FAILURE1);
1988
1989 wm_common_register_window_manager_change ((GFunc) on_window_manager_change, builder);
1990
1991 croma_settings = g_settings_new ("org.cafe.Croma.general");
1992
1993 setup_dialog (builder, croma_settings);
1994
1995 g_object_set (ctk_settings_get_default (), "ctk-button-images", TRUE(!(0)), NULL((void*)0));
1996
1997 ctk_main ();
1998
1999 g_object_unref (croma_settings);
2000 g_object_unref (builder);
2001 return 0;
2002}
2003
2004/*
2005 * vim: sw=2 ts=8 cindent noai bs=2
2006 */