File: | capplets/keybindings/cafe-keybinding-properties.c |
Warning: | line 1016, column 14 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
30 | typedef 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 | |
43 | typedef enum { |
44 | COMPARISON_NONE = 0, |
45 | COMPARISON_GT, |
46 | COMPARISON_LT, |
47 | COMPARISON_EQ |
48 | } Comparison; |
49 | |
50 | typedef 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 | |
64 | enum |
65 | { |
66 | DESCRIPTION_COLUMN, |
67 | KEYENTRY_COLUMN, |
68 | N_COLUMNS |
69 | }; |
70 | |
71 | typedef 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 | |
92 | static gboolean block_accels = FALSE(0); |
93 | static CtkWidget *custom_shortcut_dialog = NULL((void*)0); |
94 | static CtkWidget *custom_shortcut_name_entry = NULL((void*)0); |
95 | static CtkWidget *custom_shortcut_command_entry = NULL((void*)0); |
96 | |
97 | static 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 | |
102 | static CtkBuilder * |
103 | create_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 | |
118 | static 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 | |
137 | static gboolean |
138 | binding_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 | |
161 | static void |
162 | accel_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 | |
198 | static void |
199 | description_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 | |
222 | static gboolean |
223 | keybinding_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 | |
244 | static void |
245 | keybinding_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 | |
260 | static void |
261 | keybinding_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 | |
279 | static void |
280 | keybinding_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 | |
297 | static int |
298 | keyentry_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 | |
356 | static void |
357 | clear_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 | |
424 | typedef struct { |
425 | const char *key; |
426 | const char *path; |
427 | const char *schema; |
428 | gboolean found; |
429 | } KeyMatchData; |
430 | |
431 | static 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 | |
459 | static 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 | |
472 | static 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 | |
518 | static gboolean |
519 | count_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 | |
528 | static void |
529 | ensure_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 | |
545 | static void |
546 | find_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 | |
572 | static void |
573 | append_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 | |
726 | static void |
727 | parse_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 | |
878 | static gboolean |
879 | strv_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 | |
890 | static void |
891 | append_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)); |
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 | |
973 | static void |
974 | append_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; |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
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 | |
1030 | static void |
1031 | reload_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 | |
1096 | static void |
1097 | key_entry_controlling_key_changed (GSettings *settings, gchar *key, gpointer user_data) |
1098 | { |
1099 | reload_key_entries (user_data); |
1100 | } |
1101 | |
1102 | static 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 | |
1162 | static 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 | |
1182 | static 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 | |
1197 | static 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 | |
1213 | static 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 | |
1365 | static void |
1366 | accel_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 | |
1395 | static void |
1396 | description_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 | |
1424 | typedef struct |
1425 | { |
1426 | CtkTreeView *tree_view; |
1427 | CtkTreePath *path; |
1428 | CtkTreeViewColumn *column; |
1429 | } IdleData; |
1430 | |
1431 | static gboolean |
1432 | real_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 | |
1444 | static gboolean |
1445 | edit_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 | |
1480 | static gboolean |
1481 | remove_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 | |
1519 | static void |
1520 | update_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 | |
1545 | static gchar * |
1546 | find_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 | |
1588 | static void |
1589 | add_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 | |
1668 | static void |
1669 | start_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 | |
1715 | static gboolean |
1716 | start_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 */ |
1779 | static 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 | |
1789 | static void |
1790 | cb_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 | |
1826 | static void |
1827 | selection_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 | |
1846 | static void |
1847 | cb_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 | |
1870 | static void |
1871 | setup_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 | |
1968 | static void |
1969 | on_window_manager_change (const char *wm_name, CtkBuilder *builder) |
1970 | { |
1971 | reload_key_entries (builder); |
1972 | } |
1973 | |
1974 | int |
1975 | main (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 | */ |