File: | plugins/keybindings/csd_keybindings-manager.c |
Warning: | line 431, column 25 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 | } |