Mercurial > audlegacy-plugins
comparison src/hotkey/plugin.c @ 1543:ec4e8ec829b1
Include global hotkey plugin in build system (src/hotkey)
author | Sascha Hlusiak <contact@saschahlusiak.de> |
---|---|
date | Fri, 31 Aug 2007 22:48:53 +0200 |
parents | |
children | a9af4f1aede9 |
comparison
equal
deleted
inserted
replaced
1542:3e8d69cd4bf1 | 1543:ec4e8ec829b1 |
---|---|
1 /* -*- Mode: C; indent-tabs: t; c-basic-offset: 9; tab-width: 9 -*- */ | |
2 /* | |
3 * This file is part of audacious-hotkey plugin for audacious | |
4 * | |
5 * Copyright (c) 2007 Sascha Hlusiak <contact@saschahlusiak.de> | |
6 * Name: plugin.c | |
7 * Description: plugin.c | |
8 * | |
9 * Part of this code is from itouch-ctrl plugin. | |
10 * Authors of itouch-ctrl are listed below: | |
11 * | |
12 * Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov@gmail.com> | |
13 * | |
14 * Part of this code are from xmms-itouch plugin. | |
15 * Authors of xmms-itouch are listed below: | |
16 * | |
17 * Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi> | |
18 * Bryn Davies <curious@ihug.com.au> | |
19 * Jonathan A. Davis <davis@jdhouse.org> | |
20 * Jeremy Tan <nsx@nsx.homeip.net> | |
21 * | |
22 * audacious-hotkey is free software; you can redistribute it and/or modify | |
23 * it under the terms of the GNU General Public License as published by | |
24 * the Free Software Foundation; either version 2 of the License, or | |
25 * (at your option) any later version. | |
26 * | |
27 * audacious-hotkey is distributed in the hope that it will be useful, | |
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
30 * GNU General Public License for more details. | |
31 * | |
32 * You should have received a copy of the GNU General Public License | |
33 * along with audacious-hotkey; if not, write to the Free Software | |
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
35 */ | |
36 | |
37 #include <config.h> | |
38 | |
39 #include <stdio.h> | |
40 #include <stdlib.h> | |
41 #include <X11/Xlib.h> | |
42 #include <X11/keysym.h> | |
43 #include <X11/XF86keysym.h> | |
44 | |
45 #include <gtk/gtk.h> | |
46 #include <gdk/gdkx.h> | |
47 #include <gdk/gdkkeysyms.h> | |
48 #include <audacious/plugin.h> | |
49 #include <audacious/auddrct.h> | |
50 #include <audacious/configdb.h> | |
51 | |
52 #ifdef ENABLE_NLS | |
53 #ifdef HAVE_AUDACIOUS_I18N_H | |
54 #include <audacious/i18n.h> | |
55 #else | |
56 #ifdef HAVE_DCGETTEXT | |
57 #include <libintl.h> | |
58 #define _(String) dgettext(PACKAGE, String) | |
59 #else | |
60 #define _(String) (String) | |
61 #endif | |
62 #endif | |
63 #else | |
64 #define _(String) (String) | |
65 #endif | |
66 | |
67 /* for xmms_show_message () */ | |
68 #include <audacious/util.h> | |
69 | |
70 | |
71 /* func defs */ | |
72 void x_display_init (void); | |
73 static void get_offending_modifiers (Display * dpy); | |
74 static void init (void); | |
75 static void grab_keys (); | |
76 static void ungrab_keys (); | |
77 static gboolean handle_keyevent(int keycode, int state); | |
78 static gboolean setup_filter(); | |
79 static void release_filter(); | |
80 | |
81 static void load_config (void); | |
82 static void save_config (void); | |
83 static void configure (void); | |
84 static void clear_keyboard (GtkWidget *widget, gpointer data); | |
85 | |
86 void cancel_callback (GtkWidget *widget, gpointer data); | |
87 void ok_callback (GtkWidget *widget, gpointer data); | |
88 static void about (void); | |
89 static void cleanup (void); | |
90 | |
91 typedef struct { | |
92 gint vol_increment; | |
93 gint vol_decrement; | |
94 | |
95 /* keyboard */ | |
96 gint mute, mute_mask; | |
97 gint vol_down, vol_down_mask; | |
98 gint vol_up, vol_up_mask; | |
99 gint play, play_mask; | |
100 gint stop, stop_mask; | |
101 gint pause, pause_mask; | |
102 gint prev_track, prev_track_mask; | |
103 gint next_track, next_track_mask; | |
104 gint jump_to_file, jump_to_file_mask; | |
105 gint toggle_win, toggle_win_mask; | |
106 | |
107 gint forward, forward_mask; | |
108 gint backward, backward_mask; | |
109 } PluginConfig; | |
110 | |
111 PluginConfig plugin_cfg; | |
112 | |
113 static Display *xdisplay = NULL; | |
114 static Window x_root_window = 0; | |
115 static gint grabbed = 0; | |
116 static gboolean loaded = FALSE; | |
117 static unsigned int numlock_mask = 0; | |
118 static unsigned int scrolllock_mask = 0; | |
119 static unsigned int capslock_mask = 0; | |
120 | |
121 | |
122 | |
123 typedef struct { | |
124 GtkWidget *keytext; | |
125 gint key, mask; | |
126 } KeyControls; | |
127 | |
128 typedef struct { | |
129 KeyControls play; | |
130 KeyControls stop; | |
131 KeyControls pause; | |
132 KeyControls prev; | |
133 KeyControls next; | |
134 KeyControls up; | |
135 KeyControls down; | |
136 KeyControls mute; | |
137 KeyControls jump_to_file; | |
138 KeyControls forward; | |
139 KeyControls backward; | |
140 KeyControls toggle_win; | |
141 } ConfigurationControls; | |
142 | |
143 static GeneralPlugin audacioushotkey = | |
144 { | |
145 NULL, | |
146 NULL, | |
147 "Global Hotkey", | |
148 init, | |
149 about, | |
150 configure, | |
151 cleanup | |
152 }; | |
153 | |
154 GeneralPlugin *hotkey_gplist[] = { &audacioushotkey, NULL }; | |
155 DECLARE_PLUGIN(hotkey, NULL, NULL, NULL, NULL, NULL, hotkey_gplist, NULL, NULL); | |
156 | |
157 | |
158 | |
159 /* | |
160 * plugin activated | |
161 */ | |
162 static void init (void) | |
163 { | |
164 x_display_init ( ); | |
165 setup_filter(); | |
166 load_config ( ); | |
167 grab_keys (); | |
168 | |
169 loaded = TRUE; | |
170 } | |
171 | |
172 /* check X display */ | |
173 void x_display_init (void) | |
174 { | |
175 if (xdisplay != NULL) return; | |
176 xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); | |
177 x_root_window = GDK_WINDOW_XID(gdk_get_default_root_window()); | |
178 get_offending_modifiers(xdisplay); | |
179 } | |
180 | |
181 /* Taken from xbindkeys */ | |
182 static void get_offending_modifiers (Display * dpy) | |
183 { | |
184 int i; | |
185 XModifierKeymap *modmap; | |
186 KeyCode nlock, slock; | |
187 static int mask_table[8] = { | |
188 ShiftMask, LockMask, ControlMask, Mod1Mask, | |
189 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask | |
190 }; | |
191 | |
192 nlock = XKeysymToKeycode (dpy, XK_Num_Lock); | |
193 slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); | |
194 | |
195 /* | |
196 * Find out the masks for the NumLock and ScrollLock modifiers, | |
197 * so that we can bind the grabs for when they are enabled too. | |
198 */ | |
199 modmap = XGetModifierMapping (dpy); | |
200 | |
201 if (modmap != NULL && modmap->max_keypermod > 0) | |
202 { | |
203 for (i = 0; i < 8 * modmap->max_keypermod; i++) | |
204 { | |
205 if (modmap->modifiermap[i] == nlock && nlock != 0) | |
206 numlock_mask = mask_table[i / modmap->max_keypermod]; | |
207 else if (modmap->modifiermap[i] == slock && slock != 0) | |
208 scrolllock_mask = mask_table[i / modmap->max_keypermod]; | |
209 } | |
210 } | |
211 | |
212 capslock_mask = LockMask; | |
213 | |
214 if (modmap) | |
215 XFreeModifiermap (modmap); | |
216 } | |
217 | |
218 /* handle keys */ | |
219 static gboolean handle_keyevent (int keycode, int state) | |
220 { | |
221 gint current_volume, old_volume; | |
222 static gint volume_static = 0; | |
223 gboolean play, mute; | |
224 | |
225 /* playing or not */ | |
226 play = audacious_drct_is_playing (); | |
227 | |
228 /* get current volume */ | |
229 audacious_drct_get_volume_main (¤t_volume); | |
230 old_volume = current_volume; | |
231 if (current_volume) | |
232 { | |
233 /* volume is not mute */ | |
234 mute = FALSE; | |
235 } else { | |
236 /* volume is mute */ | |
237 mute = TRUE; | |
238 } | |
239 | |
240 state &= ~(scrolllock_mask | numlock_mask | capslock_mask); | |
241 | |
242 /* mute the playback */ | |
243 if ((keycode == plugin_cfg.mute) && (state == plugin_cfg.mute_mask)) | |
244 { | |
245 if (!mute) | |
246 { | |
247 volume_static = current_volume; | |
248 audacious_drct_set_main_volume (0); | |
249 mute = TRUE; | |
250 } else { | |
251 audacious_drct_set_main_volume (volume_static); | |
252 mute = FALSE; | |
253 } | |
254 return TRUE; | |
255 } | |
256 | |
257 /* decreace volume */ | |
258 if ((keycode == plugin_cfg.vol_down) && (state == plugin_cfg.vol_down_mask)) | |
259 { | |
260 if (mute) | |
261 { | |
262 current_volume = old_volume; | |
263 old_volume = 0; | |
264 mute = FALSE; | |
265 } | |
266 | |
267 if ((current_volume -= plugin_cfg.vol_decrement) < 0) | |
268 { | |
269 current_volume = 0; | |
270 } | |
271 | |
272 if (current_volume != old_volume) | |
273 { | |
274 audacious_drct_set_main_volume (current_volume); | |
275 } | |
276 | |
277 old_volume = current_volume; | |
278 return TRUE; | |
279 } | |
280 | |
281 /* increase volume */ | |
282 if ((keycode == plugin_cfg.vol_up) && (state == plugin_cfg.vol_up_mask)) | |
283 { | |
284 if (mute) | |
285 { | |
286 current_volume = old_volume; | |
287 old_volume = 0; | |
288 mute = FALSE; | |
289 } | |
290 | |
291 if ((current_volume += plugin_cfg.vol_increment) > 100) | |
292 { | |
293 current_volume = 100; | |
294 } | |
295 | |
296 if (current_volume != old_volume) | |
297 { | |
298 audacious_drct_set_main_volume (current_volume); | |
299 } | |
300 | |
301 old_volume = current_volume; | |
302 return TRUE; | |
303 } | |
304 | |
305 /* play */ | |
306 if ((keycode == plugin_cfg.play) && (state == plugin_cfg.play_mask)) | |
307 { | |
308 if (!play) | |
309 { | |
310 audacious_drct_play (); | |
311 } else { | |
312 audacious_drct_pause (); | |
313 } | |
314 return TRUE; | |
315 } | |
316 | |
317 /* pause */ | |
318 if ((keycode == plugin_cfg.pause) && (state == plugin_cfg.pause_mask)) | |
319 { | |
320 if (!play) audacious_drct_play (); | |
321 else audacious_drct_pause (); | |
322 | |
323 return TRUE; | |
324 } | |
325 | |
326 /* stop */ | |
327 if ((keycode == plugin_cfg.stop) && (state == plugin_cfg.stop_mask)) | |
328 { | |
329 audacious_drct_stop (); | |
330 return TRUE; | |
331 } | |
332 | |
333 /* prev track */ | |
334 if ((keycode == plugin_cfg.prev_track) && (state == plugin_cfg.prev_track_mask)) | |
335 { | |
336 audacious_drct_playlist_prev (); | |
337 return TRUE; | |
338 } | |
339 | |
340 /* next track */ | |
341 if ((keycode == plugin_cfg.next_track) && (state == plugin_cfg.next_track_mask)) | |
342 { | |
343 audacious_drct_playlist_next (); | |
344 return TRUE; | |
345 } | |
346 | |
347 /* forward */ | |
348 if ((keycode == plugin_cfg.forward) && (state == plugin_cfg.forward_mask)) | |
349 { | |
350 gint time = audacious_drct_get_output_time(); | |
351 time += 5000; /* Jump 5s into future */ | |
352 audacious_drct_jump_to_time(time); | |
353 return TRUE; | |
354 } | |
355 | |
356 /* backward */ | |
357 if ((keycode == plugin_cfg.backward) && (state == plugin_cfg.backward_mask)) | |
358 { | |
359 gint time = audacious_drct_get_output_time(); | |
360 if (time > 5000) time -= 5000; /* Jump 5s back */ | |
361 else time = 0; | |
362 audacious_drct_jump_to_time(time); | |
363 return TRUE; | |
364 } | |
365 | |
366 /* Open Jump-To-File dialog */ | |
367 if ((keycode == plugin_cfg.jump_to_file) && (state == plugin_cfg.jump_to_file_mask)) | |
368 { | |
369 audacious_drct_show_jtf_box(); | |
370 return TRUE; | |
371 } | |
372 | |
373 /* Toggle Windows */ | |
374 if ((keycode == plugin_cfg.toggle_win) && (state == plugin_cfg.toggle_win_mask)) | |
375 { | |
376 static gboolean is_main, is_eq, is_pl; | |
377 is_main = audacious_drct_main_win_is_visible(); | |
378 if (is_main) { | |
379 is_pl = audacious_drct_pl_win_is_visible(); | |
380 is_eq = audacious_drct_eq_win_is_visible(); | |
381 audacious_drct_main_win_toggle(FALSE); | |
382 audacious_drct_pl_win_toggle(FALSE); | |
383 audacious_drct_eq_win_toggle(FALSE); | |
384 } else { | |
385 audacious_drct_main_win_toggle(TRUE); | |
386 audacious_drct_pl_win_toggle(is_pl); | |
387 audacious_drct_eq_win_toggle(is_eq); | |
388 } | |
389 return TRUE; | |
390 } | |
391 | |
392 return FALSE; | |
393 } | |
394 | |
395 static GdkFilterReturn | |
396 gdk_filter(GdkXEvent *xevent, | |
397 GdkEvent *event, | |
398 gpointer data) | |
399 { | |
400 XKeyEvent *keyevent = (XKeyEvent*)xevent; | |
401 | |
402 if (((XEvent*)keyevent)->type != KeyPress) | |
403 return -1; | |
404 | |
405 if (handle_keyevent(keyevent->keycode, keyevent->state)) | |
406 return GDK_FILTER_REMOVE; | |
407 | |
408 return GDK_FILTER_CONTINUE; | |
409 } | |
410 | |
411 static gboolean | |
412 setup_filter() | |
413 { | |
414 gdk_window_add_filter(gdk_get_default_root_window(), | |
415 gdk_filter, | |
416 NULL); | |
417 | |
418 return TRUE; | |
419 } | |
420 | |
421 static void release_filter() | |
422 { | |
423 gdk_window_remove_filter(gdk_get_default_root_window(), | |
424 gdk_filter, | |
425 NULL); | |
426 } | |
427 | |
428 /* load plugin configuration */ | |
429 static void load_config (void) | |
430 { | |
431 ConfigDb *cfdb; | |
432 | |
433 if (xdisplay == NULL) x_display_init(); | |
434 | |
435 /* default volume level */ | |
436 plugin_cfg.vol_increment = 4; | |
437 plugin_cfg.vol_decrement = 4; | |
438 | |
439 plugin_cfg.mute = XKeysymToKeycode(xdisplay, XF86XK_AudioMute); | |
440 plugin_cfg.mute_mask = 0; | |
441 plugin_cfg.vol_down = XKeysymToKeycode(xdisplay, XF86XK_AudioLowerVolume); | |
442 plugin_cfg.vol_down_mask = 0; | |
443 plugin_cfg.vol_up = XKeysymToKeycode(xdisplay, XF86XK_AudioRaiseVolume); | |
444 plugin_cfg.vol_up_mask = 0; | |
445 plugin_cfg.play = XKeysymToKeycode(xdisplay, XF86XK_AudioPlay); | |
446 plugin_cfg.play_mask = 0; | |
447 plugin_cfg.pause = XKeysymToKeycode(xdisplay, XF86XK_AudioPause); | |
448 plugin_cfg.pause_mask = 0; | |
449 plugin_cfg.stop = XKeysymToKeycode(xdisplay, XF86XK_AudioStop); | |
450 plugin_cfg.stop_mask = 0; | |
451 plugin_cfg.prev_track = XKeysymToKeycode(xdisplay, XF86XK_AudioPrev); | |
452 plugin_cfg.prev_track_mask = 0; | |
453 plugin_cfg.next_track = XKeysymToKeycode(xdisplay, XF86XK_AudioNext); | |
454 plugin_cfg.next_track_mask = 0; | |
455 plugin_cfg.jump_to_file = XKeysymToKeycode(xdisplay, XF86XK_AudioMedia); | |
456 plugin_cfg.jump_to_file_mask = 0; | |
457 plugin_cfg.forward = 0; | |
458 plugin_cfg.forward_mask = 0; | |
459 plugin_cfg.backward = XKeysymToKeycode(xdisplay, XF86XK_AudioRewind); | |
460 plugin_cfg.backward_mask = 0; | |
461 plugin_cfg.toggle_win = 0; | |
462 plugin_cfg.toggle_win_mask = 0; | |
463 | |
464 /* open configuration database */ | |
465 cfdb = bmp_cfg_db_open ( ); | |
466 | |
467 bmp_cfg_db_get_int (cfdb, "globalHotkey", "mute", &plugin_cfg.mute); | |
468 bmp_cfg_db_get_int (cfdb, "globalHotkey", "mute_mask", &plugin_cfg.mute_mask); | |
469 bmp_cfg_db_get_int (cfdb, "globalHotkey", "vol_down", &plugin_cfg.vol_down); | |
470 bmp_cfg_db_get_int (cfdb, "globalHotkey", "vol_down_mask", &plugin_cfg.vol_down_mask); | |
471 bmp_cfg_db_get_int (cfdb, "globalHotkey", "vol_up", &plugin_cfg.vol_up); | |
472 bmp_cfg_db_get_int (cfdb, "globalHotkey", "vol_up_mask", &plugin_cfg.vol_up_mask); | |
473 bmp_cfg_db_get_int (cfdb, "globalHotkey", "play", &plugin_cfg.play); | |
474 bmp_cfg_db_get_int (cfdb, "globalHotkey", "play_mask", &plugin_cfg.play_mask); | |
475 bmp_cfg_db_get_int (cfdb, "globalHotkey", "pause", &plugin_cfg.pause); | |
476 bmp_cfg_db_get_int (cfdb, "globalHotkey", "pause_mask", &plugin_cfg.pause_mask); | |
477 bmp_cfg_db_get_int (cfdb, "globalHotkey", "stop", &plugin_cfg.stop); | |
478 bmp_cfg_db_get_int (cfdb, "globalHotkey", "stop_mask", &plugin_cfg.stop_mask); | |
479 bmp_cfg_db_get_int (cfdb, "globalHotkey", "prev_track", &plugin_cfg.prev_track); | |
480 bmp_cfg_db_get_int (cfdb, "globalHotkey", "prev_track_mask", &plugin_cfg.prev_track_mask); | |
481 bmp_cfg_db_get_int (cfdb, "globalHotkey", "next_track", &plugin_cfg.next_track); | |
482 bmp_cfg_db_get_int (cfdb, "globalHotkey", "next_track_mask", &plugin_cfg.next_track_mask); | |
483 bmp_cfg_db_get_int (cfdb, "globalHotkey", "jump_to_file", &plugin_cfg.jump_to_file); | |
484 bmp_cfg_db_get_int (cfdb, "globalHotkey", "jump_to_file_mask", &plugin_cfg.jump_to_file_mask); | |
485 bmp_cfg_db_get_int (cfdb, "globalHotkey", "forward", &plugin_cfg.forward); | |
486 bmp_cfg_db_get_int (cfdb, "globalHotkey", "forward_mask", &plugin_cfg.forward_mask); | |
487 bmp_cfg_db_get_int (cfdb, "globalHotkey", "backward", &plugin_cfg.backward); | |
488 bmp_cfg_db_get_int (cfdb, "globalHotkey", "backward_mask", &plugin_cfg.backward_mask); | |
489 bmp_cfg_db_get_int (cfdb, "globalHotkey", "toggle_win", &plugin_cfg.toggle_win); | |
490 bmp_cfg_db_get_int (cfdb, "globalHotkey", "toggle_win_mask", &plugin_cfg.toggle_win_mask); | |
491 | |
492 bmp_cfg_db_close (cfdb); | |
493 } | |
494 | |
495 /* save plugin configuration */ | |
496 static void save_config (void) | |
497 { | |
498 ConfigDb *cfdb; | |
499 | |
500 /* open configuration database */ | |
501 cfdb = bmp_cfg_db_open ( ); | |
502 | |
503 bmp_cfg_db_set_int (cfdb, "globalHotkey", "mute", plugin_cfg.mute); | |
504 bmp_cfg_db_set_int (cfdb, "globalHotkey", "mute_mask", plugin_cfg.mute_mask); | |
505 bmp_cfg_db_set_int (cfdb, "globalHotkey", "vol_up", plugin_cfg.vol_up); | |
506 bmp_cfg_db_set_int (cfdb, "globalHotkey", "vol_up_mask", plugin_cfg.vol_up_mask); | |
507 bmp_cfg_db_set_int (cfdb, "globalHotkey", "vol_down", plugin_cfg.vol_down); | |
508 bmp_cfg_db_set_int (cfdb, "globalHotkey", "vol_down_mask", plugin_cfg.vol_down_mask); | |
509 bmp_cfg_db_set_int (cfdb, "globalHotkey", "play", plugin_cfg.play); | |
510 bmp_cfg_db_set_int (cfdb, "globalHotkey", "play_mask", plugin_cfg.play_mask); | |
511 bmp_cfg_db_set_int (cfdb, "globalHotkey", "pause", plugin_cfg.pause); | |
512 bmp_cfg_db_set_int (cfdb, "globalHotkey", "pause_mask", plugin_cfg.pause_mask); | |
513 bmp_cfg_db_set_int (cfdb, "globalHotkey", "stop", plugin_cfg.stop); | |
514 bmp_cfg_db_set_int (cfdb, "globalHotkey", "stop_mask", plugin_cfg.stop_mask); | |
515 bmp_cfg_db_set_int (cfdb, "globalHotkey", "prev_track", plugin_cfg.prev_track); | |
516 bmp_cfg_db_set_int (cfdb, "globalHotkey", "prev_track_mask", plugin_cfg.prev_track_mask); | |
517 bmp_cfg_db_set_int (cfdb, "globalHotkey", "next_track", plugin_cfg.next_track); | |
518 bmp_cfg_db_set_int (cfdb, "globalHotkey", "next_track_mask", plugin_cfg.next_track_mask); | |
519 bmp_cfg_db_set_int (cfdb, "globalHotkey", "jump_to_file", plugin_cfg.jump_to_file); | |
520 bmp_cfg_db_set_int (cfdb, "globalHotkey", "jump_to_file_mask", plugin_cfg.jump_to_file_mask); | |
521 bmp_cfg_db_set_int (cfdb, "globalHotkey", "forward", plugin_cfg.forward); | |
522 bmp_cfg_db_set_int (cfdb, "globalHotkey", "forward_mask", plugin_cfg.forward_mask); | |
523 bmp_cfg_db_set_int (cfdb, "globalHotkey", "backward", plugin_cfg.backward); | |
524 bmp_cfg_db_set_int (cfdb, "globalHotkey", "backward_mask", plugin_cfg.backward_mask); | |
525 bmp_cfg_db_set_int (cfdb, "globalHotkey", "toggle_win", plugin_cfg.toggle_win); | |
526 bmp_cfg_db_set_int (cfdb, "globalHotkey", "toggle_win_mask", plugin_cfg.toggle_win_mask); | |
527 bmp_cfg_db_close (cfdb); | |
528 } | |
529 | |
530 static int x11_error_handler (Display *dpy, XErrorEvent *error) | |
531 { | |
532 return 0; | |
533 } | |
534 | |
535 /* grab requied keys */ | |
536 static void grab_key(KeyCode keycode, unsigned int modifier) | |
537 { | |
538 modifier &= ~(numlock_mask | capslock_mask | scrolllock_mask); | |
539 | |
540 XGrabKey (xdisplay, keycode, modifier, x_root_window, | |
541 False, GrabModeAsync, GrabModeAsync); | |
542 | |
543 if (modifier == AnyModifier) | |
544 return; | |
545 | |
546 if (numlock_mask) | |
547 XGrabKey (xdisplay, keycode, modifier | numlock_mask, | |
548 x_root_window, | |
549 False, GrabModeAsync, GrabModeAsync); | |
550 | |
551 if (capslock_mask) | |
552 XGrabKey (xdisplay, keycode, modifier | capslock_mask, | |
553 x_root_window, | |
554 False, GrabModeAsync, GrabModeAsync); | |
555 | |
556 if (scrolllock_mask) | |
557 XGrabKey (xdisplay, keycode, modifier | scrolllock_mask, | |
558 x_root_window, | |
559 False, GrabModeAsync, GrabModeAsync); | |
560 | |
561 if (numlock_mask && capslock_mask) | |
562 XGrabKey (xdisplay, keycode, modifier | numlock_mask | capslock_mask, | |
563 x_root_window, | |
564 False, GrabModeAsync, GrabModeAsync); | |
565 | |
566 if (numlock_mask && scrolllock_mask) | |
567 XGrabKey (xdisplay, keycode, modifier | numlock_mask | scrolllock_mask, | |
568 x_root_window, | |
569 False, GrabModeAsync, GrabModeAsync); | |
570 | |
571 if (capslock_mask && scrolllock_mask) | |
572 XGrabKey (xdisplay, keycode, modifier | capslock_mask | scrolllock_mask, | |
573 x_root_window, | |
574 False, GrabModeAsync, GrabModeAsync); | |
575 | |
576 if (numlock_mask && capslock_mask && scrolllock_mask) | |
577 XGrabKey (xdisplay, keycode, | |
578 modifier | numlock_mask | capslock_mask | scrolllock_mask, | |
579 x_root_window, False, GrabModeAsync, | |
580 GrabModeAsync); | |
581 } | |
582 | |
583 | |
584 static void grab_keys () | |
585 { | |
586 if (grabbed) return; | |
587 if (xdisplay == NULL) x_display_init(); | |
588 | |
589 XErrorHandler old_handler = 0; | |
590 | |
591 XSync(xdisplay, False); | |
592 old_handler = XSetErrorHandler (x11_error_handler); | |
593 | |
594 if (plugin_cfg.mute) grab_key(plugin_cfg.mute, plugin_cfg.mute_mask); | |
595 if (plugin_cfg.vol_up) grab_key(plugin_cfg.vol_up, plugin_cfg.vol_up_mask); | |
596 if (plugin_cfg.vol_down) grab_key(plugin_cfg.vol_down, plugin_cfg.vol_down_mask); | |
597 if (plugin_cfg.play) grab_key(plugin_cfg.play, plugin_cfg.play_mask); | |
598 if (plugin_cfg.pause) grab_key(plugin_cfg.pause, plugin_cfg.pause_mask); | |
599 if (plugin_cfg.stop) grab_key(plugin_cfg.stop, plugin_cfg.stop_mask); | |
600 if (plugin_cfg.prev_track) grab_key(plugin_cfg.prev_track, plugin_cfg.prev_track_mask); | |
601 if (plugin_cfg.next_track) grab_key(plugin_cfg.next_track, plugin_cfg.next_track_mask); | |
602 if (plugin_cfg.jump_to_file) grab_key(plugin_cfg.jump_to_file, plugin_cfg.jump_to_file_mask); | |
603 if (plugin_cfg.forward) grab_key(plugin_cfg.forward, plugin_cfg.forward_mask); | |
604 if (plugin_cfg.backward) grab_key(plugin_cfg.backward, plugin_cfg.backward_mask); | |
605 if (plugin_cfg.toggle_win) grab_key(plugin_cfg.toggle_win, plugin_cfg.toggle_win_mask); | |
606 | |
607 XSync(xdisplay, False); | |
608 XSetErrorHandler (old_handler); | |
609 | |
610 grabbed = 1; | |
611 } | |
612 /* | |
613 * plugin init end | |
614 */ | |
615 | |
616 static void set_keytext (GtkWidget *entry, gint key, gint mask) | |
617 { | |
618 gchar *text = NULL; | |
619 | |
620 if (key == 0 && mask == 0) | |
621 { | |
622 text = g_strdup(_("(none)")); | |
623 } else { | |
624 static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" }; | |
625 static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; | |
626 gchar *strings[9]; | |
627 gchar *keytext = NULL; | |
628 int i, j; | |
629 KeySym keysym; | |
630 | |
631 keysym = XKeycodeToKeysym(xdisplay, key, 0); | |
632 if (keysym == 0 || keysym == NoSymbol) | |
633 { | |
634 keytext = g_strdup_printf("#%3d", key); | |
635 } else { | |
636 keytext = g_strdup(XKeysymToString(keysym)); | |
637 } | |
638 | |
639 for (i = 0, j=0; j<7; j++) | |
640 { | |
641 if (mask & modifiers[j]) | |
642 strings[i++] = modifier_string[j]; | |
643 } | |
644 if (key != 0) strings[i++] = keytext; | |
645 strings[i] = NULL; | |
646 | |
647 text = g_strjoinv(" + ", strings); | |
648 g_free(keytext); | |
649 } | |
650 | |
651 gtk_entry_set_text(GTK_ENTRY(entry), text); | |
652 gtk_editable_set_position(GTK_EDITABLE(entry), -1); | |
653 if (text) g_free(text); | |
654 } | |
655 | |
656 static gboolean | |
657 on_entry_key_press_event(GtkWidget * widget, | |
658 GdkEventKey * event, | |
659 gpointer user_data) | |
660 { | |
661 KeyControls *controls = (KeyControls*) user_data; | |
662 int is_mod; | |
663 int mod; | |
664 | |
665 if (event->keyval == GDK_Tab) return FALSE; | |
666 mod = 0; | |
667 is_mod = 0; | |
668 | |
669 if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) | |
670 mod |= ControlMask; | |
671 | |
672 if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) | |
673 mod |= Mod1Mask; | |
674 | |
675 if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) | |
676 mod |= ShiftMask; | |
677 | |
678 if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) | |
679 mod |= Mod5Mask; | |
680 | |
681 if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) | |
682 mod |= Mod4Mask; | |
683 | |
684 if (!is_mod) { | |
685 controls->key = event->hardware_keycode; | |
686 controls->mask = mod; | |
687 } else controls->key = 0; | |
688 | |
689 set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod); | |
690 return FALSE; | |
691 } | |
692 | |
693 static gboolean | |
694 on_entry_key_release_event(GtkWidget * widget, | |
695 GdkEventKey * event, | |
696 gpointer user_data) | |
697 { | |
698 KeyControls *controls = (KeyControls*) user_data; | |
699 if (controls->key == 0) { | |
700 controls->mask = 0; | |
701 } | |
702 set_keytext(controls->keytext, controls->key, controls->mask); | |
703 return FALSE; | |
704 } | |
705 | |
706 | |
707 static void add_event_controls(GtkWidget *table, KeyControls *controls, int row, char* descr, gint key, gint mask) | |
708 { | |
709 GtkWidget *label; | |
710 GtkWidget *button; | |
711 | |
712 controls->key = key; | |
713 controls->mask = mask; | |
714 | |
715 label = gtk_label_new (_(descr)); | |
716 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, | |
717 (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); | |
718 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); | |
719 gtk_misc_set_padding (GTK_MISC (label), 3, 3); | |
720 | |
721 controls->keytext = gtk_entry_new (); | |
722 gtk_table_attach (GTK_TABLE (table), controls->keytext, 1, 2, row, row+1, | |
723 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0); | |
724 gtk_entry_set_editable (GTK_ENTRY (controls->keytext), FALSE); | |
725 | |
726 set_keytext(controls->keytext, key, mask); | |
727 g_signal_connect((gpointer)controls->keytext, "key_press_event", | |
728 G_CALLBACK(on_entry_key_press_event), controls); | |
729 g_signal_connect((gpointer)controls->keytext, "key_release_event", | |
730 G_CALLBACK(on_entry_key_release_event), controls); | |
731 | |
732 button = gtk_button_new_with_label (_("None")); | |
733 gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); | |
734 g_signal_connect (G_OBJECT (button), "clicked", | |
735 G_CALLBACK (clear_keyboard), controls); | |
736 } | |
737 | |
738 /* configuration window */ | |
739 static void configure (void) | |
740 { | |
741 ConfigurationControls *controls; | |
742 GtkWidget *window; | |
743 GtkWidget *main_vbox, *vbox; | |
744 GtkWidget *hbox; | |
745 GtkWidget *alignment; | |
746 GtkWidget *frame; | |
747 GtkWidget *label; | |
748 GtkWidget *image; | |
749 GtkWidget *table; | |
750 GtkWidget *button_box, *button; | |
751 | |
752 if (!xdisplay) x_display_init(); | |
753 | |
754 #ifdef ENABLE_NLS | |
755 bind_textdomain_codeset(PACKAGE, "UTF-8"); | |
756 #endif | |
757 | |
758 load_config ( ); | |
759 | |
760 ungrab_keys(); | |
761 | |
762 controls = (ConfigurationControls*)g_malloc(sizeof(ConfigurationControls)); | |
763 if (!controls) | |
764 { | |
765 printf ("Faild to allocate memory for ConfigurationControls structure!\n" | |
766 "Aborting!"); | |
767 return; | |
768 } | |
769 | |
770 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | |
771 gtk_window_set_title (GTK_WINDOW (window), _("Global Hotkey Plugin Configuration")); | |
772 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ALWAYS); | |
773 gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); | |
774 gtk_window_set_resizable (GTK_WINDOW (window), FALSE); | |
775 gtk_container_set_border_width (GTK_CONTAINER (window), 5); | |
776 | |
777 main_vbox = gtk_vbox_new (FALSE, 4); | |
778 gtk_container_add (GTK_CONTAINER (window), main_vbox); | |
779 | |
780 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
781 gtk_box_pack_start (GTK_BOX (main_vbox), alignment, FALSE, TRUE, 0); | |
782 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); | |
783 hbox = gtk_hbox_new (FALSE, 2); | |
784 gtk_container_add (GTK_CONTAINER (alignment), hbox); | |
785 image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); | |
786 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); | |
787 label = gtk_label_new (_("Press a key combination inside a text field.")); | |
788 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); | |
789 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); | |
790 | |
791 label = gtk_label_new (NULL); | |
792 gtk_label_set_markup (GTK_LABEL (label), _("<b>Playback:</b>")); | |
793 frame = gtk_frame_new (NULL); | |
794 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
795 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
796 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
797 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
798 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
799 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
800 vbox = gtk_vbox_new (FALSE, 2); | |
801 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
802 label = gtk_label_new (NULL); | |
803 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
804 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
805 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
806 gtk_label_set_markup (GTK_LABEL (label), | |
807 _("<i>Configure keys which controls Audacious playback.</i>")); | |
808 table = gtk_table_new (4, 3, FALSE); | |
809 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
810 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
811 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
812 | |
813 /* prev track */ | |
814 add_event_controls(table, &controls->prev, 0, _("Previous Track:"), | |
815 plugin_cfg.prev_track, plugin_cfg.prev_track_mask); | |
816 | |
817 add_event_controls(table, &controls->play, 1, _("Play/Pause:"), | |
818 plugin_cfg.play, plugin_cfg.play_mask); | |
819 | |
820 add_event_controls(table, &controls->pause, 2, _("Pause:"), | |
821 plugin_cfg.pause, plugin_cfg.pause_mask); | |
822 | |
823 add_event_controls(table, &controls->stop, 3, _("Stop:"), | |
824 plugin_cfg.stop, plugin_cfg.stop_mask); | |
825 | |
826 add_event_controls(table, &controls->next, 4, _("Next Track:"), | |
827 plugin_cfg.next_track, plugin_cfg.next_track_mask); | |
828 | |
829 add_event_controls(table, &controls->forward, 5, _("Forward 5 sec.:"), | |
830 plugin_cfg.forward, plugin_cfg.forward_mask); | |
831 | |
832 add_event_controls(table, &controls->backward, 6, _("Rewind 5 sec.:"), | |
833 plugin_cfg.backward, plugin_cfg.backward_mask); | |
834 | |
835 | |
836 label = gtk_label_new (NULL); | |
837 gtk_label_set_markup (GTK_LABEL (label), _("<b>Volume Control:</b>")); | |
838 frame = gtk_frame_new (NULL); | |
839 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
840 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
841 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
842 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
843 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
844 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
845 vbox = gtk_vbox_new (FALSE, 2); | |
846 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
847 label = gtk_label_new (NULL); | |
848 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
849 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
850 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
851 gtk_label_set_markup (GTK_LABEL (label), | |
852 _("<i>Configure keys which controls music volume.</i>")); | |
853 table = gtk_table_new (3, 3, FALSE); | |
854 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
855 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
856 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
857 | |
858 | |
859 | |
860 add_event_controls(table, &controls->mute, 0, _("Mute:"), | |
861 plugin_cfg.mute, plugin_cfg.mute_mask); | |
862 | |
863 add_event_controls(table, &controls->up, 1, _("Volume Up:"), | |
864 plugin_cfg.vol_up, plugin_cfg.vol_up_mask); | |
865 | |
866 add_event_controls(table, &controls->down, 2, _("Volume Down:"), | |
867 plugin_cfg.vol_down, plugin_cfg.vol_down_mask); | |
868 | |
869 | |
870 label = gtk_label_new (NULL); | |
871 gtk_label_set_markup (GTK_LABEL (label), _("<b>Player:</b>")); | |
872 frame = gtk_frame_new (NULL); | |
873 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
874 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
875 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
876 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
877 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
878 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
879 vbox = gtk_vbox_new (FALSE, 2); | |
880 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
881 label = gtk_label_new (NULL); | |
882 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
883 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
884 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
885 gtk_label_set_markup (GTK_LABEL (label), | |
886 _("<i>Configure keys which control the player.</i>")); | |
887 table = gtk_table_new (3, 2, FALSE); | |
888 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
889 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
890 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
891 | |
892 add_event_controls(table, &controls->jump_to_file, 0, _("Jump to File:"), | |
893 plugin_cfg.jump_to_file, plugin_cfg.jump_to_file_mask); | |
894 | |
895 add_event_controls(table, &controls->toggle_win, 1, _("Toggle Player Windows:"), | |
896 plugin_cfg.toggle_win, plugin_cfg.toggle_win_mask); | |
897 | |
898 | |
899 button_box = gtk_hbutton_box_new ( ); | |
900 gtk_box_pack_start (GTK_BOX (main_vbox), button_box, FALSE, TRUE, 6); | |
901 gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END); | |
902 gtk_box_set_spacing (GTK_BOX (button_box), 4); | |
903 | |
904 button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); | |
905 gtk_container_add (GTK_CONTAINER (button_box), button); | |
906 g_signal_connect (G_OBJECT (button), "clicked", | |
907 G_CALLBACK (cancel_callback), controls); | |
908 | |
909 button = gtk_button_new_from_stock (GTK_STOCK_OK); | |
910 gtk_container_add (GTK_CONTAINER (button_box), button); | |
911 g_signal_connect (G_OBJECT (button), "clicked", | |
912 G_CALLBACK (ok_callback), controls); | |
913 | |
914 gtk_widget_show_all (GTK_WIDGET (window)); | |
915 } | |
916 /* configuration window end */ | |
917 | |
918 static void about (void) | |
919 { | |
920 static GtkWidget *dialog; | |
921 | |
922 #ifdef ENABLE_NLS | |
923 bind_textdomain_codeset(PACKAGE, "UTF-8"); | |
924 #endif | |
925 | |
926 dialog = xmms_show_message (_("About Global Hotkey Plugin"), | |
927 _("Global Hotkey Plugin version " VERSION "\n\n" | |
928 "Copyright (C) 2007 Sascha Hlusiak <contact@saschahlusiak.de>\n\n" | |
929 | |
930 "Parts of the plugin source are from itouch-ctrl plugin.\n" | |
931 "Authors of itouch-ctrl are listed below:\n" | |
932 "Copyright (C) 2006 - 2007 Vladimir Paskov <vlado.paskov@gmail.com>\n\n" | |
933 | |
934 "Parts of the plugin source are from xmms-itouch plugin.\n" | |
935 "Authors of xmms-itouch are listed below:\n" | |
936 "Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi>\n" | |
937 " Bryn Davies <curious@ihug.com.au>\n" | |
938 " Jonathan A. Davis <davis@jdhouse.org>\n" | |
939 " Jeremy Tan <nsx@nsx.homeip.net>\n\n" | |
940 ), | |
941 _("Ok"), TRUE, NULL, NULL); | |
942 | |
943 gtk_signal_connect(GTK_OBJECT(dialog), "destroy", | |
944 GTK_SIGNAL_FUNC(gtk_widget_destroyed), &dialog); | |
945 } | |
946 | |
947 /* Clear keys */ | |
948 static void clear_keyboard (GtkWidget *widget, gpointer data) | |
949 { | |
950 KeyControls *spins = (KeyControls*)data; | |
951 spins->key = 0; | |
952 spins->mask = 0; | |
953 set_keytext(spins->keytext, 0, 0); | |
954 } | |
955 | |
956 void cancel_callback (GtkWidget *widget, gpointer data) | |
957 { | |
958 if (loaded) | |
959 { | |
960 grab_keys (); | |
961 } | |
962 if (data) g_free(data); | |
963 | |
964 gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); | |
965 } | |
966 | |
967 void ok_callback (GtkWidget *widget, gpointer data) | |
968 { | |
969 ConfigurationControls *controls= (ConfigurationControls*)data; | |
970 | |
971 plugin_cfg.play = controls->play.key; | |
972 plugin_cfg.play_mask = controls->play.mask; | |
973 | |
974 plugin_cfg.pause = controls->pause.key; | |
975 plugin_cfg.pause_mask = controls->pause.mask; | |
976 | |
977 plugin_cfg.stop = controls->stop.key; | |
978 plugin_cfg.stop_mask = controls->stop.mask; | |
979 | |
980 plugin_cfg.prev_track = controls->prev.key; | |
981 plugin_cfg.prev_track_mask = controls->prev.mask; | |
982 | |
983 plugin_cfg.next_track = controls->next.key; | |
984 plugin_cfg.next_track_mask = controls->next.mask; | |
985 | |
986 plugin_cfg.forward = controls->forward.key; | |
987 plugin_cfg.forward_mask = controls->forward.mask; | |
988 | |
989 plugin_cfg.backward = controls->backward.key; | |
990 plugin_cfg.backward_mask = controls->backward.mask; | |
991 | |
992 plugin_cfg.vol_up = controls->up.key; | |
993 plugin_cfg.vol_up_mask = controls->up.mask; | |
994 | |
995 plugin_cfg.vol_down = controls->down.key; | |
996 plugin_cfg.vol_down_mask = controls->down.mask; | |
997 | |
998 plugin_cfg.mute = controls->mute.key; | |
999 plugin_cfg.mute_mask = controls->mute.mask; | |
1000 | |
1001 plugin_cfg.jump_to_file = controls->jump_to_file.key; | |
1002 plugin_cfg.jump_to_file_mask = controls->jump_to_file.mask; | |
1003 | |
1004 plugin_cfg.toggle_win= controls->toggle_win.key; | |
1005 plugin_cfg.toggle_win_mask = controls->toggle_win.mask; | |
1006 | |
1007 save_config ( ); | |
1008 | |
1009 if (loaded) | |
1010 { | |
1011 grab_keys (); | |
1012 } | |
1013 | |
1014 if (data) g_free(data); | |
1015 | |
1016 gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); | |
1017 } | |
1018 | |
1019 /* | |
1020 * plugin cleanup | |
1021 */ | |
1022 static void cleanup (void) | |
1023 { | |
1024 if (!loaded) return; | |
1025 ungrab_keys (); | |
1026 release_filter(); | |
1027 loaded = FALSE; | |
1028 } | |
1029 | |
1030 static void ungrab_keys () | |
1031 { | |
1032 if (!grabbed) return; | |
1033 if (!xdisplay) return; | |
1034 | |
1035 XUngrabKey (xdisplay, AnyKey, AnyModifier, x_root_window); | |
1036 | |
1037 grabbed = 0; | |
1038 } | |
1039 |