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