File: | plugins/keybindings/csd_keybindings-manager.c |
Warning: | line 435, column 9 Access of the heap area at index 2, while it holds only 2 'char *' elements |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||
2 | * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> | ||||
3 | * | ||||
4 | * This program is free software; you can redistribute it and/or modify | ||||
5 | * it under the terms of the GNU General Public License as published by | ||||
6 | * the Free Software Foundation; either version 2 of the License, or | ||||
7 | * (at your option) any later version. | ||||
8 | * | ||||
9 | * This program is distributed in the hope that it will be useful, | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
12 | * GNU General Public License for more details. | ||||
13 | * | ||||
14 | * You should have received a copy of the GNU General Public License | ||||
15 | * along with this program; if not, write to the Free Software | ||||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
17 | * | ||||
18 | */ | ||||
19 | |||||
20 | #include "config.h" | ||||
21 | |||||
22 | #include <sys/types.h> | ||||
23 | #include <sys/wait.h> | ||||
24 | #include <stdlib.h> | ||||
25 | #include <stdio.h> | ||||
26 | #include <unistd.h> | ||||
27 | #include <string.h> | ||||
28 | #include <errno(*__errno_location ()).h> | ||||
29 | |||||
30 | #include <locale.h> | ||||
31 | |||||
32 | #include <glib.h> | ||||
33 | #include <glib/gi18n.h> | ||||
34 | #include <cdk/cdk.h> | ||||
35 | #include <cdk/cdkx.h> | ||||
36 | #include <ctk/ctk.h> | ||||
37 | #include <X11/keysym.h> | ||||
38 | #include <gio/gio.h> | ||||
39 | #include <dconf.h> | ||||
40 | |||||
41 | #include "cafe-settings-profile.h" | ||||
42 | #include "csd_keybindings-manager.h" | ||||
43 | #include "dconf-util.h" | ||||
44 | |||||
45 | #include "csd_keygrab.h" | ||||
46 | #include "eggaccelerators.h" | ||||
47 | |||||
48 | #define GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/" "/org/cafe/desktop/keybindings/" | ||||
49 | #define CUSTOM_KEYBINDING_SCHEMA"org.cafe.control-center.keybinding" "org.cafe.control-center.keybinding" | ||||
50 | |||||
51 | typedef struct { | ||||
52 | char *binding_str; | ||||
53 | char *action; | ||||
54 | char *settings_path; | ||||
55 | Key key; | ||||
56 | Key previous_key; | ||||
57 | } Binding; | ||||
58 | |||||
59 | struct CsdKeybindingsManagerPrivate | ||||
60 | { | ||||
61 | DConfClient *client; | ||||
62 | GSList *binding_list; | ||||
63 | GSList *screens; | ||||
64 | }; | ||||
65 | |||||
66 | static void csd_keybindings_manager_finalize (GObject *object); | ||||
67 | |||||
68 | G_DEFINE_TYPE_WITH_PRIVATE (CsdKeybindingsManager, csd_keybindings_manager, G_TYPE_OBJECT)static void csd_keybindings_manager_init (CsdKeybindingsManager *self); static void csd_keybindings_manager_class_init (CsdKeybindingsManagerClass *klass); static GType csd_keybindings_manager_get_type_once ( void); static gpointer csd_keybindings_manager_parent_class = ((void*)0); static gint CsdKeybindingsManager_private_offset ; static void csd_keybindings_manager_class_intern_init (gpointer klass) { csd_keybindings_manager_parent_class = g_type_class_peek_parent (klass); if (CsdKeybindingsManager_private_offset != 0) g_type_class_adjust_private_offset (klass, &CsdKeybindingsManager_private_offset); csd_keybindings_manager_class_init ((CsdKeybindingsManagerClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer csd_keybindings_manager_get_instance_private (CsdKeybindingsManager *self) { return (((gpointer) ((guint8 *) (self) + (glong) (CsdKeybindingsManager_private_offset)))) ; } GType csd_keybindings_manager_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); (void) (0 ? (gpointer) * ( &static_g_define_type_id) : ((void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = csd_keybindings_manager_get_type_once (); (__extension__ ( { _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); 0 ? (void) (*( &static_g_define_type_id) = (g_define_type_id)) : (void) 0 ; g_once_init_leave_pointer ((&static_g_define_type_id), ( gpointer) (guintptr) (g_define_type_id)); })) ; } return static_g_define_type_id ; } __attribute__ ((__noinline__)) static GType csd_keybindings_manager_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CsdKeybindingsManager" ), sizeof (CsdKeybindingsManagerClass), (GClassInitFunc)(void (*)(void)) csd_keybindings_manager_class_intern_init, sizeof (CsdKeybindingsManager), (GInstanceInitFunc)(void (*)(void)) csd_keybindings_manager_init, (GTypeFlags) 0); { {{ CsdKeybindingsManager_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CsdKeybindingsManagerPrivate )); };} } return g_define_type_id; } | ||||
69 | |||||
70 | static gpointer manager_object = NULL((void*)0); | ||||
71 | |||||
72 | static GSList * | ||||
73 | get_screens_list (void) | ||||
74 | { | ||||
75 | GSList *list = NULL((void*)0); | ||||
76 | |||||
77 | list = g_slist_append (list, cdk_screen_get_default ()); | ||||
78 | |||||
79 | return list; | ||||
80 | } | ||||
81 | |||||
82 | static gboolean | ||||
83 | parse_binding (Binding *binding) | ||||
84 | { | ||||
85 | gboolean success; | ||||
86 | |||||
87 | g_return_val_if_fail (binding != NULL, FALSE)do { if ((binding != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "binding != NULL" ); return ((0)); } } while (0); | ||||
88 | |||||
89 | binding->key.keysym = 0; | ||||
90 | binding->key.state = 0; | ||||
91 | g_free (binding->key.keycodes); | ||||
92 | binding->key.keycodes = NULL((void*)0); | ||||
93 | |||||
94 | if (binding->binding_str == NULL((void*)0) || | ||||
95 | binding->binding_str[0] == '\0' || | ||||
96 | g_strcmp0 (binding->binding_str, "Disabled") == 0 || | ||||
97 | g_strcmp0 (binding->binding_str, "disabled") == 0 ) { | ||||
98 | return FALSE(0); | ||||
99 | } | ||||
100 | |||||
101 | success = egg_accelerator_parse_virtual (binding->binding_str, | ||||
102 | &binding->key.keysym, | ||||
103 | &binding->key.keycodes, | ||||
104 | &binding->key.state); | ||||
105 | |||||
106 | if (!success) | ||||
107 | g_warning (_("Key binding (%s) is invalid")gettext ("Key binding (%s) is invalid"), binding->settings_path); | ||||
108 | |||||
109 | return success; | ||||
110 | } | ||||
111 | |||||
112 | static gint | ||||
113 | compare_bindings (gconstpointer a, | ||||
114 | gconstpointer b) | ||||
115 | { | ||||
116 | Binding *key_a = (Binding *) a; | ||||
117 | char *key_b = (char *) b; | ||||
118 | |||||
119 | return g_strcmp0 (key_b, key_a->settings_path); | ||||
120 | } | ||||
121 | |||||
122 | static gboolean | ||||
123 | bindings_get_entry (CsdKeybindingsManager *manager, | ||||
124 | const char *settings_path) | ||||
125 | { | ||||
126 | GSettings *settings; | ||||
127 | Binding *new_binding; | ||||
128 | GSList *tmp_elem; | ||||
129 | char *action = NULL((void*)0); | ||||
130 | char *key = NULL((void*)0); | ||||
131 | |||||
132 | if (!settings_path) { | ||||
133 | return FALSE(0); | ||||
134 | } | ||||
135 | |||||
136 | /* Get entries for this binding */ | ||||
137 | settings = g_settings_new_with_path (CUSTOM_KEYBINDING_SCHEMA"org.cafe.control-center.keybinding", settings_path); | ||||
138 | action = g_settings_get_string (settings, "action"); | ||||
139 | key = g_settings_get_string (settings, "binding"); | ||||
140 | g_object_unref (settings); | ||||
141 | |||||
142 | if (!action || !key) { | ||||
143 | g_warning (_("Key binding (%s) is incomplete")gettext ("Key binding (%s) is incomplete"), settings_path); | ||||
144 | g_free (action); | ||||
145 | g_free (key); | ||||
146 | return FALSE(0); | ||||
147 | } | ||||
148 | |||||
149 | g_debug ("keybindings: get entries from '%s' (action: '%s', key: '%s')", settings_path, action, key); | ||||
150 | |||||
151 | tmp_elem = g_slist_find_custom (manager->priv->binding_list, | ||||
152 | settings_path, | ||||
153 | compare_bindings); | ||||
154 | |||||
155 | if (!tmp_elem) { | ||||
156 | new_binding = g_new0 (Binding, 1)((Binding *) g_malloc0_n ((1), sizeof (Binding))); | ||||
157 | } else { | ||||
158 | new_binding = (Binding *) tmp_elem->data; | ||||
159 | g_free (new_binding->binding_str); | ||||
160 | g_free (new_binding->action); | ||||
161 | g_free (new_binding->settings_path); | ||||
162 | |||||
163 | new_binding->previous_key.keysym = new_binding->key.keysym; | ||||
164 | new_binding->previous_key.state = new_binding->key.state; | ||||
165 | new_binding->previous_key.keycodes = new_binding->key.keycodes; | ||||
166 | new_binding->key.keycodes = NULL((void*)0); | ||||
167 | } | ||||
168 | |||||
169 | new_binding->binding_str = key; | ||||
170 | new_binding->action = action; | ||||
171 | new_binding->settings_path = g_strdup (settings_path)g_strdup_inline (settings_path); | ||||
172 | |||||
173 | if (parse_binding (new_binding)) { | ||||
174 | if (!tmp_elem) | ||||
175 | manager->priv->binding_list = g_slist_prepend (manager->priv->binding_list, new_binding); | ||||
176 | } else { | ||||
177 | g_free (new_binding->binding_str); | ||||
178 | g_free (new_binding->action); | ||||
179 | g_free (new_binding->settings_path); | ||||
180 | g_free (new_binding->previous_key.keycodes); | ||||
181 | g_free (new_binding); | ||||
182 | |||||
183 | if (tmp_elem) | ||||
184 | manager->priv->binding_list = g_slist_delete_link (manager->priv->binding_list, tmp_elem); | ||||
185 | return FALSE(0); | ||||
186 | } | ||||
187 | |||||
188 | return TRUE(!(0)); | ||||
189 | } | ||||
190 | |||||
191 | static void | ||||
192 | bindings_clear (CsdKeybindingsManager *manager) | ||||
193 | { | ||||
194 | CsdKeybindingsManagerPrivate *p = manager->priv; | ||||
195 | GSList *l; | ||||
196 | |||||
197 | if (p->binding_list != NULL((void*)0)) | ||||
198 | { | ||||
199 | for (l = p->binding_list; l; l = l->next) { | ||||
200 | Binding *b = l->data; | ||||
201 | g_free (b->binding_str); | ||||
202 | g_free (b->action); | ||||
203 | g_free (b->settings_path); | ||||
204 | g_free (b->previous_key.keycodes); | ||||
205 | g_free (b->key.keycodes); | ||||
206 | g_free (b); | ||||
207 | } | ||||
208 | g_slist_free (p->binding_list); | ||||
209 | p->binding_list = NULL((void*)0); | ||||
210 | } | ||||
211 | } | ||||
212 | |||||
213 | static void | ||||
214 | bindings_get_entries (CsdKeybindingsManager *manager) | ||||
215 | { | ||||
216 | gchar **custom_list = NULL((void*)0); | ||||
217 | gint i; | ||||
218 | |||||
219 | bindings_clear (manager); | ||||
220 | |||||
221 | custom_list = dconf_util_list_subdirs (GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/", FALSE(0)); | ||||
222 | |||||
223 | if (custom_list != NULL((void*)0)) | ||||
224 | { | ||||
225 | for (i = 0; custom_list[i] != NULL((void*)0); i++) | ||||
226 | { | ||||
227 | gchar *settings_path; | ||||
228 | settings_path = g_strdup_printf("%s%s", GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/", custom_list[i]); | ||||
229 | bindings_get_entry (manager, settings_path); | ||||
230 | g_free (settings_path); | ||||
231 | } | ||||
232 | g_strfreev (custom_list); | ||||
233 | } | ||||
234 | |||||
235 | } | ||||
236 | |||||
237 | static gboolean | ||||
238 | same_keycode (const Key *key, const Key *other) | ||||
239 | { | ||||
240 | if (key->keycodes != NULL((void*)0) && other->keycodes != NULL((void*)0)) { | ||||
241 | guint *c; | ||||
242 | |||||
243 | for (c = key->keycodes; *c; ++c) { | ||||
244 | if (key_uses_keycode (other, *c)) | ||||
245 | return TRUE(!(0)); | ||||
246 | } | ||||
247 | } | ||||
248 | return FALSE(0); | ||||
249 | } | ||||
250 | |||||
251 | static gboolean | ||||
252 | same_key (const Key *key, const Key *other) | ||||
253 | { | ||||
254 | if (key->state == other->state) { | ||||
255 | if (key->keycodes != NULL((void*)0) && other->keycodes != NULL((void*)0)) { | ||||
256 | guint *c1, *c2; | ||||
257 | |||||
258 | for (c1 = key->keycodes, c2 = other->keycodes; | ||||
259 | *c1 || *c2; ++c1, ++c2) { | ||||
260 | if (*c1 != *c2) | ||||
261 | return FALSE(0); | ||||
262 | } | ||||
263 | } else if (key->keycodes != NULL((void*)0) || other->keycodes != NULL((void*)0)) | ||||
264 | return FALSE(0); | ||||
265 | |||||
266 | |||||
267 | return TRUE(!(0)); | ||||
268 | } | ||||
269 | |||||
270 | return FALSE(0); | ||||
271 | } | ||||
272 | |||||
273 | static gboolean | ||||
274 | key_already_used (CsdKeybindingsManager *manager, | ||||
275 | Binding *binding) | ||||
276 | { | ||||
277 | GSList *li; | ||||
278 | |||||
279 | for (li = manager->priv->binding_list; li != NULL((void*)0); li = li->next) { | ||||
280 | Binding *tmp_binding = (Binding*) li->data; | ||||
281 | |||||
282 | if (tmp_binding != binding && | ||||
283 | same_keycode (&tmp_binding->key, &binding->key) && | ||||
284 | tmp_binding->key.state == binding->key.state) { | ||||
285 | return TRUE(!(0)); | ||||
286 | } | ||||
287 | } | ||||
288 | |||||
289 | return FALSE(0); | ||||
290 | } | ||||
291 | |||||
292 | static void | ||||
293 | binding_unregister_keys (CsdKeybindingsManager *manager) | ||||
294 | { | ||||
295 | CdkDisplay *dpy; | ||||
296 | GSList *li; | ||||
297 | gboolean need_flush = FALSE(0); | ||||
298 | |||||
299 | dpy = cdk_display_get_default (); | ||||
300 | cdk_x11_display_error_trap_push (dpy); | ||||
301 | |||||
302 | for (li = manager->priv->binding_list; li != NULL((void*)0); li = li->next) { | ||||
303 | Binding *binding = (Binding *) li->data; | ||||
304 | |||||
305 | if (binding->key.keycodes) { | ||||
306 | need_flush = TRUE(!(0)); | ||||
307 | grab_key_unsafe (&binding->key, FALSE(0), manager->priv->screens); | ||||
308 | } | ||||
309 | } | ||||
310 | |||||
311 | if (need_flush) | ||||
312 | cdk_display_flush (dpy); | ||||
313 | |||||
314 | cdk_x11_display_error_trap_pop_ignored (dpy); | ||||
315 | } | ||||
316 | |||||
317 | static void | ||||
318 | binding_register_keys (CsdKeybindingsManager *manager) | ||||
319 | { | ||||
320 | GSList *li; | ||||
321 | CdkDisplay *dpy; | ||||
322 | gboolean need_flush = FALSE(0); | ||||
323 | |||||
324 | dpy = cdk_display_get_default (); | ||||
325 | cdk_x11_display_error_trap_push (dpy); | ||||
326 | |||||
327 | /* Now check for changes and grab new key if not already used */ | ||||
328 | for (li = manager->priv->binding_list; li != NULL((void*)0); li = li->next) { | ||||
329 | Binding *binding = (Binding *) li->data; | ||||
330 | |||||
331 | if (!same_key (&binding->previous_key, &binding->key)) { | ||||
332 | /* Ungrab key if it changed and not clashing with previously set binding */ | ||||
333 | if (!key_already_used (manager, binding)) { | ||||
334 | gint i; | ||||
335 | |||||
336 | need_flush = TRUE(!(0)); | ||||
337 | if (binding->previous_key.keycodes) { | ||||
338 | grab_key_unsafe (&binding->previous_key, FALSE(0), manager->priv->screens); | ||||
339 | } | ||||
340 | grab_key_unsafe (&binding->key, TRUE(!(0)), manager->priv->screens); | ||||
341 | |||||
342 | binding->previous_key.keysym = binding->key.keysym; | ||||
343 | binding->previous_key.state = binding->key.state; | ||||
344 | g_free (binding->previous_key.keycodes); | ||||
345 | for (i = 0; binding->key.keycodes[i]; ++i); | ||||
346 | binding->previous_key.keycodes = g_new0 (guint, i)((guint *) g_malloc0_n ((i), sizeof (guint))); | ||||
347 | for (i = 0; binding->key.keycodes[i]; ++i) | ||||
348 | binding->previous_key.keycodes[i] = binding->key.keycodes[i]; | ||||
349 | } else | ||||
350 | g_warning ("Key binding (%s) is already in use", binding->binding_str); | ||||
351 | } | ||||
352 | } | ||||
353 | |||||
354 | if (need_flush) | ||||
355 | cdk_display_flush (dpy); | ||||
356 | if (cdk_x11_display_error_trap_pop (dpy)) | ||||
357 | g_warning ("Grab failed for some keys, another application may already have access the them."); | ||||
358 | |||||
359 | } | ||||
360 | |||||
361 | extern char **environ; | ||||
362 | |||||
363 | static char * | ||||
364 | screen_exec_display_string (CdkScreen *screen) | ||||
365 | { | ||||
366 | GString *str; | ||||
367 | const char *old_display; | ||||
368 | char *p; | ||||
369 | |||||
370 | g_return_val_if_fail (CDK_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((screen)); GType __t = ((cdk_screen_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; })))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char* ) (__func__)), "CDK_IS_SCREEN (screen)"); return (((void*)0)) ; } } while (0); | ||||
371 | |||||
372 | old_display = cdk_display_get_name (cdk_screen_get_display (screen)); | ||||
373 | |||||
374 | str = g_string_new ("DISPLAY="); | ||||
375 | g_string_append (str, old_display)(__builtin_constant_p (old_display) ? __extension__ ({ const char * const __val = (old_display); g_string_append_len_inline (str , __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + ! (__val))) : (gssize) -1); }) : g_string_append_len_inline (str , old_display, (gssize) -1)); | ||||
376 | |||||
377 | p = strrchr (str->str, '.'); | ||||
378 | if (p && p > strchr (str->str, ':')) { | ||||
379 | g_string_truncate (str, p - str->str)g_string_truncate_inline (str, p - str->str); | ||||
380 | } | ||||
381 | |||||
382 | g_string_append_printf (str, ".%d", cdk_x11_screen_get_screen_number (screen)); | ||||
383 | |||||
384 | return g_string_free (str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((str) , ((0))) : g_string_free_and_steal (str)) : (g_string_free) ( (str), ((0)))); | ||||
385 | } | ||||
386 | |||||
387 | /** | ||||
388 | * get_exec_environment: | ||||
389 | * | ||||
390 | * Description: Modifies the current program environment to | ||||
391 | * ensure that $DISPLAY is set such that a launched application | ||||
392 | * inheriting this environment would appear on screen. | ||||
393 | * | ||||
394 | * Returns: a newly-allocated %NULL-terminated array of strings or | ||||
395 | * %NULL on error. Use g_strfreev() to free it. | ||||
396 | * | ||||
397 | * mainly ripped from egg_screen_exec_display_string in | ||||
398 | * cafe-panel/egg-screen-exec.c | ||||
399 | **/ | ||||
400 | static char ** | ||||
401 | get_exec_environment (XEvent *xevent) | ||||
402 | { | ||||
403 | char **retval = NULL((void*)0); | ||||
404 | int i; | ||||
405 | int display_index = -1; | ||||
406 | CdkScreen *screen = NULL((void*)0); | ||||
407 | CdkWindow *window = cdk_x11_window_lookup_for_display (cdk_display_get_default (), xevent->xkey.root); | ||||
408 | |||||
409 | if (window) { | ||||
410 | screen = cdk_window_get_screen (window); | ||||
411 | } | ||||
412 | |||||
413 | g_return_val_if_fail (CDK_IS_SCREEN (screen), NULL)do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((screen)); GType __t = ((cdk_screen_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; })))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char* ) (__func__)), "CDK_IS_SCREEN (screen)"); return (((void*)0)) ; } } while (0); | ||||
414 | |||||
415 | for (i = 0; environ [i]; i++) { | ||||
416 | if (!strncmp (environ [i], "DISPLAY", 7)) { | ||||
417 | display_index = i; | ||||
418 | } | ||||
419 | } | ||||
420 | |||||
421 | if (display_index == -1) { | ||||
422 | display_index = i++; | ||||
423 | } | ||||
424 | |||||
425 | retval = g_new (char *, i + 1)((char * *) g_malloc_n ((i + 1), sizeof (char *))); | ||||
426 | |||||
427 | for (i = 0; environ [i]; i++) { | ||||
428 | if (i
| ||||
429 | retval [i] = screen_exec_display_string (screen); | ||||
430 | } else { | ||||
431 | retval [i] = g_strdup (environ [i])g_strdup_inline (environ [i]); | ||||
432 | } | ||||
433 | } | ||||
434 | |||||
435 | retval [i] = NULL((void*)0); | ||||
| |||||
436 | |||||
437 | return retval; | ||||
438 | } | ||||
439 | |||||
440 | static CdkFilterReturn | ||||
441 | keybindings_filter (CdkXEvent *cdk_xevent, | ||||
442 | CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)), | ||||
443 | CsdKeybindingsManager *manager) | ||||
444 | { | ||||
445 | XEvent *xevent = (XEvent *) cdk_xevent; | ||||
446 | GSList *li; | ||||
447 | |||||
448 | if (xevent->type != KeyPress2) { | ||||
| |||||
449 | return CDK_FILTER_CONTINUE; | ||||
450 | } | ||||
451 | |||||
452 | for (li = manager->priv->binding_list; li != NULL((void*)0); li = li->next) { | ||||
453 | Binding *binding = (Binding *) li->data; | ||||
454 | |||||
455 | if (match_key (&binding->key, xevent)) { | ||||
456 | GError *error = NULL((void*)0); | ||||
457 | gboolean retval; | ||||
458 | gchar **argv = NULL((void*)0); | ||||
459 | gchar **envp = NULL((void*)0); | ||||
460 | |||||
461 | g_return_val_if_fail (binding->action != NULL, CDK_FILTER_CONTINUE)do { if ((binding->action != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "binding->action != NULL" ); return (CDK_FILTER_CONTINUE); } } while (0); | ||||
462 | |||||
463 | if (!g_shell_parse_argv (binding->action, | ||||
464 | NULL((void*)0), &argv, | ||||
465 | &error)) { | ||||
466 | return CDK_FILTER_CONTINUE; | ||||
467 | } | ||||
468 | |||||
469 | envp = get_exec_environment (xevent); | ||||
470 | |||||
471 | retval = g_spawn_async (NULL((void*)0), | ||||
472 | argv, | ||||
473 | envp, | ||||
474 | G_SPAWN_SEARCH_PATH, | ||||
475 | NULL((void*)0), | ||||
476 | NULL((void*)0), | ||||
477 | NULL((void*)0), | ||||
478 | &error); | ||||
479 | g_strfreev (argv); | ||||
480 | g_strfreev (envp); | ||||
481 | |||||
482 | if (!retval) { | ||||
483 | CtkWidget *dialog = ctk_message_dialog_new (NULL((void*)0), 0, CTK_MESSAGE_WARNING, | ||||
484 | CTK_BUTTONS_CLOSE, | ||||
485 | _("Error while trying to run (%s)\n"\gettext ("Error while trying to run (%s)\n" "which is linked to the key (%s)" ) | ||||
486 | "which is linked to the key (%s)")gettext ("Error while trying to run (%s)\n" "which is linked to the key (%s)" ), | ||||
487 | binding->action, | ||||
488 | binding->binding_str); | ||||
489 | g_signal_connect (dialog,g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) | ||||
490 | "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) | ||||
491 | G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0) | ||||
492 | NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) ( ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags ) 0); | ||||
493 | ctk_widget_show (dialog); | ||||
494 | } | ||||
495 | return CDK_FILTER_REMOVE; | ||||
496 | } | ||||
497 | } | ||||
498 | return CDK_FILTER_CONTINUE; | ||||
499 | } | ||||
500 | |||||
501 | static void | ||||
502 | bindings_callback (DConfClient *client G_GNUC_UNUSED__attribute__ ((__unused__)), | ||||
503 | gchar *prefix G_GNUC_UNUSED__attribute__ ((__unused__)), | ||||
504 | GStrv changes G_GNUC_UNUSED__attribute__ ((__unused__)), | ||||
505 | gchar *tag G_GNUC_UNUSED__attribute__ ((__unused__)), | ||||
506 | CsdKeybindingsManager *manager) | ||||
507 | { | ||||
508 | g_debug ("keybindings: received 'changed' signal from dconf"); | ||||
509 | |||||
510 | binding_unregister_keys (manager); | ||||
511 | |||||
512 | bindings_get_entries (manager); | ||||
513 | |||||
514 | binding_register_keys (manager); | ||||
515 | } | ||||
516 | |||||
517 | gboolean | ||||
518 | csd_keybindings_manager_start (CsdKeybindingsManager *manager, | ||||
519 | GError **error G_GNUC_UNUSED__attribute__ ((__unused__))) | ||||
520 | { | ||||
521 | CdkDisplay *dpy; | ||||
522 | CdkScreen *screen; | ||||
523 | CdkWindow *window; | ||||
524 | Display *xdpy; | ||||
525 | Window xwindow; | ||||
526 | XWindowAttributes atts; | ||||
527 | |||||
528 | g_debug ("Starting keybindings manager"); | ||||
529 | cafe_settings_profile_start (NULL); | ||||
530 | |||||
531 | dpy = cdk_display_get_default (); | ||||
532 | xdpy = CDK_DISPLAY_XDISPLAY (dpy)(cdk_x11_display_get_xdisplay (dpy)); | ||||
533 | |||||
534 | screen = cdk_display_get_default_screen (dpy); | ||||
535 | window = cdk_screen_get_root_window (screen); | ||||
536 | xwindow = CDK_WINDOW_XID (window)(cdk_x11_window_get_xid (window)); | ||||
537 | |||||
538 | cdk_window_add_filter (window, | ||||
539 | (CdkFilterFunc) keybindings_filter, | ||||
540 | manager); | ||||
541 | |||||
542 | cdk_x11_display_error_trap_push (dpy); | ||||
543 | /* Add KeyPressMask to the currently reportable event masks */ | ||||
544 | XGetWindowAttributes (xdpy, xwindow, &atts); | ||||
545 | XSelectInput (xdpy, xwindow, atts.your_event_mask | KeyPressMask(1L<<0)); | ||||
546 | cdk_x11_display_error_trap_pop_ignored (dpy); | ||||
547 | |||||
548 | manager->priv->screens = get_screens_list (); | ||||
549 | |||||
550 | manager->priv->binding_list = NULL((void*)0); | ||||
551 | bindings_get_entries (manager); | ||||
552 | binding_register_keys (manager); | ||||
553 | |||||
554 | manager->priv->client = dconf_client_new (); | ||||
555 | dconf_client_watch_fast (manager->priv->client, GSETTINGS_KEYBINDINGS_DIR"/org/cafe/desktop/keybindings/"); | ||||
556 | g_signal_connect (manager->priv->client, "changed", G_CALLBACK (bindings_callback), manager)g_signal_connect_data ((manager->priv->client), ("changed" ), (((GCallback) (bindings_callback))), (manager), ((void*)0) , (GConnectFlags) 0); | ||||
557 | |||||
558 | cafe_settings_profile_end (NULL); | ||||
559 | |||||
560 | return TRUE(!(0)); | ||||
561 | } | ||||
562 | |||||
563 | void | ||||
564 | csd_keybindings_manager_stop (CsdKeybindingsManager *manager) | ||||
565 | { | ||||
566 | CsdKeybindingsManagerPrivate *p = manager->priv; | ||||
567 | GSList *l; | ||||
568 | |||||
569 | g_debug ("Stopping keybindings manager"); | ||||
570 | |||||
571 | if (p->client != NULL((void*)0)) { | ||||
572 | g_object_unref (p->client); | ||||
573 | p->client = NULL((void*)0); | ||||
574 | } | ||||
575 | |||||
576 | for (l = p->screens; l; l = l->next) { | ||||
577 | CdkScreen *screen = l->data; | ||||
578 | cdk_window_remove_filter (cdk_screen_get_root_window (screen), | ||||
579 | (CdkFilterFunc) keybindings_filter, | ||||
580 | manager); | ||||
581 | } | ||||
582 | |||||
583 | binding_unregister_keys (manager); | ||||
584 | bindings_clear (manager); | ||||
585 | |||||
586 | g_slist_free (p->screens); | ||||
587 | p->screens = NULL((void*)0); | ||||
588 | } | ||||
589 | |||||
590 | static void | ||||
591 | csd_keybindings_manager_class_init (CsdKeybindingsManagerClass *klass) | ||||
592 | { | ||||
593 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); | ||||
594 | |||||
595 | object_class->finalize = csd_keybindings_manager_finalize; | ||||
596 | } | ||||
597 | |||||
598 | static void | ||||
599 | csd_keybindings_manager_init (CsdKeybindingsManager *manager) | ||||
600 | { | ||||
601 | manager->priv = csd_keybindings_manager_get_instance_private (manager); | ||||
602 | |||||
603 | } | ||||
604 | |||||
605 | static void | ||||
606 | csd_keybindings_manager_finalize (GObject *object) | ||||
607 | { | ||||
608 | CsdKeybindingsManager *keybindings_manager; | ||||
609 | |||||
610 | g_return_if_fail (object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "object != NULL") ; return; } } while (0); | ||||
611 | g_return_if_fail (CSD_IS_KEYBINDINGS_MANAGER (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((object)); GType __t = ((csd_keybindings_manager_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; })))))) { } else { g_return_if_fail_warning (((gchar*) 0 ), ((const char*) (__func__)), "CSD_IS_KEYBINDINGS_MANAGER (object)" ); return; } } while (0); | ||||
612 | |||||
613 | keybindings_manager = CSD_KEYBINDINGS_MANAGER (object)((((CsdKeybindingsManager*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((object)), ((csd_keybindings_manager_get_type ())))))); | ||||
614 | |||||
615 | g_return_if_fail (keybindings_manager->priv != NULL)do { if ((keybindings_manager->priv != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__ )), "keybindings_manager->priv != NULL"); return; } } while (0); | ||||
616 | |||||
617 | G_OBJECT_CLASS (csd_keybindings_manager_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((csd_keybindings_manager_parent_class)), (((GType) ((20) << (2))))))))->finalize (object); | ||||
618 | } | ||||
619 | |||||
620 | CsdKeybindingsManager * | ||||
621 | csd_keybindings_manager_new (void) | ||||
622 | { | ||||
623 | if (manager_object != NULL((void*)0)) { | ||||
624 | g_object_ref (manager_object)((__typeof__ (manager_object)) (g_object_ref) (manager_object )); | ||||
625 | } else { | ||||
626 | manager_object = g_object_new (CSD_TYPE_KEYBINDINGS_MANAGER(csd_keybindings_manager_get_type ()), NULL((void*)0)); | ||||
627 | g_object_add_weak_pointer (manager_object, | ||||
628 | (gpointer *) &manager_object); | ||||
629 | } | ||||
630 | |||||
631 | return CSD_KEYBINDINGS_MANAGER (manager_object)((((CsdKeybindingsManager*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((manager_object)), ((csd_keybindings_manager_get_type ())))))); | ||||
632 | } |