Mercurial > audlegacy-plugins
comparison src/hotkey/plugin.c @ 2330:0be42d832217
Splitted core/gui/grabbing sources; Fixed memory leak when closing configuration dialog.
| author | Sascha Hlusiak <contact@saschahlusiak.de> |
|---|---|
| date | Sun, 20 Jan 2008 14:52:44 +0100 |
| parents | 515f9c741a5c |
| children | ad45d65e9ae7 |
comparison
equal
deleted
inserted
replaced
| 2316:62391135da44 | 2330:0be42d832217 |
|---|---|
| 1 /* -*- Mode: C; indent-tabs: t; c-basic-offset: 9; tab-width: 9 -*- */ | |
| 2 /* | 1 /* |
| 3 * This file is part of audacious-hotkey plugin for audacious | 2 * This file is part of audacious-hotkey plugin for audacious |
| 4 * | 3 * |
| 5 * Copyright (c) 2007 - 2008 Sascha Hlusiak <contact@saschahlusiak.de> | 4 * Copyright (c) 2007 - 2008 Sascha Hlusiak <contact@saschahlusiak.de> |
| 6 * Name: plugin.c | 5 * Name: plugin.c |
| 35 */ | 34 */ |
| 36 | 35 |
| 37 #include <config.h> | 36 #include <config.h> |
| 38 | 37 |
| 39 #include <stdio.h> | 38 #include <stdio.h> |
| 40 #include <stdlib.h> | |
| 41 #include <X11/Xlib.h> | |
| 42 #include <X11/keysym.h> | |
| 43 #include <X11/XF86keysym.h> | 39 #include <X11/XF86keysym.h> |
| 44 | 40 |
| 45 #include <gtk/gtk.h> | |
| 46 #include <gdk/gdkx.h> | 41 #include <gdk/gdkx.h> |
| 47 #include <gdk/gdkkeysyms.h> | |
| 48 #include <audacious/plugin.h> | 42 #include <audacious/plugin.h> |
| 49 #include <audacious/auddrct.h> | 43 #include <audacious/auddrct.h> |
| 50 #include <audacious/configdb.h> | 44 #include <audacious/configdb.h> |
| 51 | 45 |
| 52 #include <audacious/i18n.h> | 46 #include <audacious/i18n.h> |
| 53 | 47 |
| 54 /* for audacious_info_dialog () */ | 48 #include "plugin.h" |
| 55 #include <audacious/util.h> | 49 #include "gui.h" |
| 50 #include "grab.h" | |
| 56 | 51 |
| 57 | 52 |
| 58 /* func defs */ | 53 /* func defs */ |
| 59 void x_display_init (void); | |
| 60 static void get_offending_modifiers (Display * dpy); | |
| 61 static void init (void); | 54 static void init (void); |
| 62 static void grab_keys (); | |
| 63 static void ungrab_keys (); | |
| 64 static gboolean handle_keyevent(int keycode, int state, int type); | |
| 65 static gboolean setup_filter(); | |
| 66 static void release_filter(); | |
| 67 | |
| 68 static void load_config (void); | |
| 69 static void save_config (void); | |
| 70 static void configure (void); | |
| 71 static void clear_keyboard (GtkWidget *widget, gpointer data); | |
| 72 | |
| 73 void cancel_callback (GtkWidget *widget, gpointer data); | |
| 74 void ok_callback (GtkWidget *widget, gpointer data); | |
| 75 static void about (void); | |
| 76 static void cleanup (void); | 55 static void cleanup (void); |
| 77 | 56 |
| 78 #define TYPE_KEY 0 | 57 |
| 79 #define TYPE_MOUSE 1 | 58 /* global vars */ |
| 80 | 59 static PluginConfig plugin_cfg; |
| 81 | |
| 82 typedef struct { | |
| 83 gint key, mask; | |
| 84 gint type; | |
| 85 } HotkeyConfiguration; | |
| 86 | |
| 87 typedef struct { | |
| 88 gint vol_increment; | |
| 89 gint vol_decrement; | |
| 90 | |
| 91 /* keyboard */ | |
| 92 HotkeyConfiguration mute; | |
| 93 HotkeyConfiguration vol_down; | |
| 94 HotkeyConfiguration vol_up; | |
| 95 HotkeyConfiguration play; | |
| 96 HotkeyConfiguration stop; | |
| 97 HotkeyConfiguration pause; | |
| 98 HotkeyConfiguration prev_track; | |
| 99 HotkeyConfiguration next_track; | |
| 100 HotkeyConfiguration jump_to_file; | |
| 101 HotkeyConfiguration toggle_win; | |
| 102 HotkeyConfiguration forward; | |
| 103 HotkeyConfiguration backward; | |
| 104 HotkeyConfiguration show_aosd; | |
| 105 } PluginConfig; | |
| 106 | |
| 107 PluginConfig plugin_cfg; | |
| 108 | |
| 109 static Display *xdisplay = NULL; | |
| 110 static Window x_root_window = 0; | |
| 111 static gint grabbed = 0; | |
| 112 static gboolean loaded = FALSE; | 60 static gboolean loaded = FALSE; |
| 113 static unsigned int numlock_mask = 0; | 61 |
| 114 static unsigned int scrolllock_mask = 0; | 62 |
| 115 static unsigned int capslock_mask = 0; | |
| 116 | |
| 117 | |
| 118 | |
| 119 typedef struct { | |
| 120 GtkWidget *keytext; | |
| 121 HotkeyConfiguration hotkey; | |
| 122 } KeyControls; | |
| 123 | |
| 124 typedef struct { | |
| 125 KeyControls play; | |
| 126 KeyControls stop; | |
| 127 KeyControls pause; | |
| 128 KeyControls prev_track; | |
| 129 KeyControls next_track; | |
| 130 KeyControls vol_up; | |
| 131 KeyControls vol_down; | |
| 132 KeyControls mute; | |
| 133 KeyControls jump_to_file; | |
| 134 KeyControls forward; | |
| 135 KeyControls backward; | |
| 136 KeyControls toggle_win; | |
| 137 KeyControls show_aosd; | |
| 138 } ConfigurationControls; | |
| 139 | 63 |
| 140 static GeneralPlugin audacioushotkey = | 64 static GeneralPlugin audacioushotkey = |
| 141 { | 65 { |
| 142 .description = "Global Hotkey", | 66 .description = "Global Hotkey", |
| 143 .init = init, | 67 .init = init, |
| 144 .about = about, | 68 .about = show_about, |
| 145 .configure = configure, | 69 .configure = show_configure, |
| 146 .cleanup = cleanup | 70 .cleanup = cleanup |
| 147 }; | 71 }; |
| 148 | 72 |
| 149 GeneralPlugin *hotkey_gplist[] = { &audacioushotkey, NULL }; | 73 GeneralPlugin *hotkey_gplist[] = { &audacioushotkey, NULL }; |
| 150 SIMPLE_GENERAL_PLUGIN(hotkey, hotkey_gplist); | 74 SIMPLE_GENERAL_PLUGIN(hotkey, hotkey_gplist); |
| 151 | 75 |
| 76 | |
| 77 | |
| 78 PluginConfig* get_config(void) | |
| 79 { | |
| 80 return &plugin_cfg; | |
| 81 } | |
| 152 | 82 |
| 153 | 83 |
| 154 /* | 84 /* |
| 155 * plugin activated | 85 * plugin activated |
| 156 */ | 86 */ |
| 157 static void init (void) | 87 static void init (void) |
| 158 { | 88 { |
| 159 x_display_init ( ); | |
| 160 setup_filter(); | 89 setup_filter(); |
| 161 load_config ( ); | 90 load_config ( ); |
| 162 grab_keys (); | 91 grab_keys ( ); |
| 163 | 92 |
| 164 loaded = TRUE; | 93 loaded = TRUE; |
| 165 } | 94 } |
| 166 | 95 |
| 167 /* check X display */ | |
| 168 void x_display_init (void) | |
| 169 { | |
| 170 if (xdisplay != NULL) return; | |
| 171 xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); | |
| 172 x_root_window = GDK_WINDOW_XID(gdk_get_default_root_window()); | |
| 173 get_offending_modifiers(xdisplay); | |
| 174 } | |
| 175 | |
| 176 /* Taken from xbindkeys */ | |
| 177 static void get_offending_modifiers (Display * dpy) | |
| 178 { | |
| 179 int i; | |
| 180 XModifierKeymap *modmap; | |
| 181 KeyCode nlock, slock; | |
| 182 static int mask_table[8] = { | |
| 183 ShiftMask, LockMask, ControlMask, Mod1Mask, | |
| 184 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask | |
| 185 }; | |
| 186 | |
| 187 nlock = XKeysymToKeycode (dpy, XK_Num_Lock); | |
| 188 slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); | |
| 189 | |
| 190 /* | |
| 191 * Find out the masks for the NumLock and ScrollLock modifiers, | |
| 192 * so that we can bind the grabs for when they are enabled too. | |
| 193 */ | |
| 194 modmap = XGetModifierMapping (dpy); | |
| 195 | |
| 196 if (modmap != NULL && modmap->max_keypermod > 0) | |
| 197 { | |
| 198 for (i = 0; i < 8 * modmap->max_keypermod; i++) | |
| 199 { | |
| 200 if (modmap->modifiermap[i] == nlock && nlock != 0) | |
| 201 numlock_mask = mask_table[i / modmap->max_keypermod]; | |
| 202 else if (modmap->modifiermap[i] == slock && slock != 0) | |
| 203 scrolllock_mask = mask_table[i / modmap->max_keypermod]; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 capslock_mask = LockMask; | |
| 208 | |
| 209 if (modmap) | |
| 210 XFreeModifiermap (modmap); | |
| 211 } | |
| 212 | |
| 213 /* handle keys */ | 96 /* handle keys */ |
| 214 static gboolean handle_keyevent (int keycode, int state, int type) | 97 gboolean handle_keyevent (int keycode, int state, int type) |
| 215 { | 98 { |
| 216 gint current_volume, old_volume; | 99 gint current_volume, old_volume; |
| 217 static gint volume_static = 0; | 100 static gint volume_static = 0; |
| 218 gboolean play, mute; | 101 gboolean play, mute; |
| 219 | 102 |
| 230 } else { | 113 } else { |
| 231 /* volume is mute */ | 114 /* volume is mute */ |
| 232 mute = TRUE; | 115 mute = TRUE; |
| 233 } | 116 } |
| 234 | 117 |
| 235 state &= ~(scrolllock_mask | numlock_mask | capslock_mask); | |
| 236 | |
| 237 /* mute the playback */ | 118 /* mute the playback */ |
| 238 if ((keycode == plugin_cfg.mute.key) && (state == plugin_cfg.mute.mask) && (type == plugin_cfg.mute.type)) | 119 if ((keycode == plugin_cfg.mute.key) && (state == plugin_cfg.mute.mask) && (type == plugin_cfg.mute.type)) |
| 239 { | 120 { |
| 240 if (!mute) | 121 if (!mute) |
| 241 { | 122 { |
| 388 } | 269 } |
| 389 | 270 |
| 390 return FALSE; | 271 return FALSE; |
| 391 } | 272 } |
| 392 | 273 |
| 393 static GdkFilterReturn | |
| 394 gdk_filter(GdkXEvent *xevent, | |
| 395 GdkEvent *event, | |
| 396 gpointer data) | |
| 397 { | |
| 398 switch (((XEvent*)xevent)->type) | |
| 399 { | |
| 400 case KeyPress: | |
| 401 { | |
| 402 XKeyEvent *keyevent = (XKeyEvent*)xevent; | |
| 403 if (handle_keyevent(keyevent->keycode, keyevent->state, TYPE_KEY)) | |
| 404 return GDK_FILTER_REMOVE; | |
| 405 break; | |
| 406 } | |
| 407 case ButtonPress: | |
| 408 { | |
| 409 XButtonEvent *buttonevent = (XButtonEvent*)xevent; | |
| 410 if (handle_keyevent(buttonevent->button, buttonevent->state, TYPE_MOUSE)) | |
| 411 return GDK_FILTER_REMOVE; | |
| 412 break; | |
| 413 } | |
| 414 default: | |
| 415 return -1; | |
| 416 } | |
| 417 | |
| 418 return GDK_FILTER_CONTINUE; | |
| 419 } | |
| 420 | |
| 421 static gboolean | |
| 422 setup_filter() | |
| 423 { | |
| 424 gdk_window_add_filter(gdk_get_default_root_window(), | |
| 425 gdk_filter, | |
| 426 NULL); | |
| 427 | |
| 428 return TRUE; | |
| 429 } | |
| 430 | |
| 431 static void release_filter() | |
| 432 { | |
| 433 gdk_window_remove_filter(gdk_get_default_root_window(), | |
| 434 gdk_filter, | |
| 435 NULL); | |
| 436 } | |
| 437 | |
| 438 /* load plugin configuration */ | 274 /* load plugin configuration */ |
| 439 static void load_config (void) | 275 void load_config (void) |
| 440 { | 276 { |
| 441 ConfigDb *cfdb; | 277 ConfigDb *cfdb; |
| 442 | 278 |
| 443 if (xdisplay == NULL) x_display_init(); | |
| 444 | |
| 445 /* default volume level */ | 279 /* default volume level */ |
| 446 plugin_cfg.vol_increment = 4; | 280 plugin_cfg.vol_increment = 4; |
| 447 plugin_cfg.vol_decrement = 4; | 281 plugin_cfg.vol_decrement = 4; |
| 448 | 282 |
| 449 #define load_key(hotkey,default) \ | 283 #define load_key(hotkey,default) \ |
| 450 plugin_cfg.hotkey.key = (default)?(XKeysymToKeycode(xdisplay, (default))):0; \ | 284 plugin_cfg.hotkey.key = (default)?(XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), (default))):0; \ |
| 451 plugin_cfg.hotkey.mask = 0; \ | 285 plugin_cfg.hotkey.mask = 0; \ |
| 452 plugin_cfg.hotkey.type = TYPE_KEY; \ | 286 plugin_cfg.hotkey.type = TYPE_KEY; \ |
| 453 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey, &plugin_cfg.hotkey.key); \ | 287 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey, &plugin_cfg.hotkey.key); \ |
| 454 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey "_mask", &plugin_cfg.hotkey.mask); \ | 288 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey "_mask", &plugin_cfg.hotkey.mask); \ |
| 455 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey "_type", &plugin_cfg.hotkey.type); | 289 aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey "_type", &plugin_cfg.hotkey.type); |
| 474 | 308 |
| 475 aud_cfg_db_close (cfdb); | 309 aud_cfg_db_close (cfdb); |
| 476 } | 310 } |
| 477 | 311 |
| 478 /* save plugin configuration */ | 312 /* save plugin configuration */ |
| 479 static void save_config (void) | 313 void save_config (void) |
| 480 { | 314 { |
| 481 ConfigDb *cfdb; | 315 ConfigDb *cfdb; |
| 482 | 316 |
| 483 #define save_key(hotkey) \ | 317 #define save_key(hotkey) \ |
| 484 aud_cfg_db_set_int (cfdb, "globalHotkey", #hotkey, plugin_cfg.hotkey.key); \ | 318 aud_cfg_db_set_int (cfdb, "globalHotkey", #hotkey, plugin_cfg.hotkey.key); \ |
| 503 save_key(show_aosd); | 337 save_key(show_aosd); |
| 504 | 338 |
| 505 aud_cfg_db_close (cfdb); | 339 aud_cfg_db_close (cfdb); |
| 506 } | 340 } |
| 507 | 341 |
| 508 static int x11_error_handler (Display *dpy, XErrorEvent *error) | |
| 509 { | |
| 510 return 0; | |
| 511 } | |
| 512 | |
| 513 /* grab required keys */ | |
| 514 static void grab_key(HotkeyConfiguration hotkey) | |
| 515 { | |
| 516 unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); | |
| 517 | |
| 518 if (hotkey.key == 0) return; | |
| 519 | |
| 520 if (hotkey.type == TYPE_KEY) | |
| 521 { | |
| 522 XGrabKey (xdisplay, hotkey.key, modifier, x_root_window, | |
| 523 False, GrabModeAsync, GrabModeAsync); | |
| 524 | |
| 525 if (modifier == AnyModifier) | |
| 526 return; | |
| 527 | |
| 528 if (numlock_mask) | |
| 529 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask, | |
| 530 x_root_window, | |
| 531 False, GrabModeAsync, GrabModeAsync); | |
| 532 | |
| 533 if (capslock_mask) | |
| 534 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask, | |
| 535 x_root_window, | |
| 536 False, GrabModeAsync, GrabModeAsync); | |
| 537 | |
| 538 if (scrolllock_mask) | |
| 539 XGrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, | |
| 540 x_root_window, | |
| 541 False, GrabModeAsync, GrabModeAsync); | |
| 542 | |
| 543 if (numlock_mask && capslock_mask) | |
| 544 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, | |
| 545 x_root_window, | |
| 546 False, GrabModeAsync, GrabModeAsync); | |
| 547 | |
| 548 if (numlock_mask && scrolllock_mask) | |
| 549 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, | |
| 550 x_root_window, | |
| 551 False, GrabModeAsync, GrabModeAsync); | |
| 552 | |
| 553 if (capslock_mask && scrolllock_mask) | |
| 554 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, | |
| 555 x_root_window, | |
| 556 False, GrabModeAsync, GrabModeAsync); | |
| 557 | |
| 558 if (numlock_mask && capslock_mask && scrolllock_mask) | |
| 559 XGrabKey (xdisplay, hotkey.key, | |
| 560 modifier | numlock_mask | capslock_mask | scrolllock_mask, | |
| 561 x_root_window, False, GrabModeAsync, | |
| 562 GrabModeAsync); | |
| 563 } | |
| 564 if (hotkey.type == TYPE_MOUSE) | |
| 565 { | |
| 566 XGrabButton (xdisplay, hotkey.key, modifier, x_root_window, | |
| 567 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 568 | |
| 569 if (modifier == AnyModifier) | |
| 570 return; | |
| 571 | |
| 572 if (numlock_mask) | |
| 573 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask, | |
| 574 x_root_window, | |
| 575 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 576 | |
| 577 if (capslock_mask) | |
| 578 XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask, | |
| 579 x_root_window, | |
| 580 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 581 | |
| 582 if (scrolllock_mask) | |
| 583 XGrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, | |
| 584 x_root_window, | |
| 585 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 586 | |
| 587 if (numlock_mask && capslock_mask) | |
| 588 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, | |
| 589 x_root_window, | |
| 590 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 591 | |
| 592 if (numlock_mask && scrolllock_mask) | |
| 593 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, | |
| 594 x_root_window, | |
| 595 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 596 | |
| 597 if (capslock_mask && scrolllock_mask) | |
| 598 XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, | |
| 599 x_root_window, | |
| 600 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); | |
| 601 | |
| 602 if (numlock_mask && capslock_mask && scrolllock_mask) | |
| 603 XGrabButton (xdisplay, hotkey.key, | |
| 604 modifier | numlock_mask | capslock_mask | scrolllock_mask, | |
| 605 x_root_window, False, ButtonPressMask, GrabModeAsync, | |
| 606 GrabModeAsync, None, None); | |
| 607 } | |
| 608 } | |
| 609 | |
| 610 static void grab_keys () | |
| 611 { | |
| 612 if (grabbed) return; | |
| 613 if (xdisplay == NULL) x_display_init(); | |
| 614 | |
| 615 XErrorHandler old_handler = 0; | |
| 616 | |
| 617 XSync(xdisplay, False); | |
| 618 old_handler = XSetErrorHandler (x11_error_handler); | |
| 619 | |
| 620 grab_key(plugin_cfg.mute); | |
| 621 grab_key(plugin_cfg.vol_up); | |
| 622 grab_key(plugin_cfg.vol_down); | |
| 623 grab_key(plugin_cfg.play); | |
| 624 grab_key(plugin_cfg.pause); | |
| 625 grab_key(plugin_cfg.stop); | |
| 626 grab_key(plugin_cfg.prev_track); | |
| 627 grab_key(plugin_cfg.next_track); | |
| 628 grab_key(plugin_cfg.jump_to_file); | |
| 629 grab_key(plugin_cfg.forward); | |
| 630 grab_key(plugin_cfg.backward); | |
| 631 grab_key(plugin_cfg.toggle_win); | |
| 632 grab_key(plugin_cfg.show_aosd); | |
| 633 | |
| 634 XSync(xdisplay, False); | |
| 635 XSetErrorHandler (old_handler); | |
| 636 | |
| 637 grabbed = 1; | |
| 638 } | |
| 639 /* | |
| 640 * plugin init end | |
| 641 */ | |
| 642 | |
| 643 static void set_keytext (GtkWidget *entry, gint key, gint mask, gint type) | |
| 644 { | |
| 645 gchar *text = NULL; | |
| 646 | |
| 647 if (key == 0 && mask == 0) | |
| 648 { | |
| 649 text = g_strdup(_("(none)")); | |
| 650 } else { | |
| 651 static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" }; | |
| 652 static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; | |
| 653 gchar *strings[9]; | |
| 654 gchar *keytext = NULL; | |
| 655 int i, j; | |
| 656 if (type == TYPE_KEY) | |
| 657 { | |
| 658 KeySym keysym; | |
| 659 keysym = XKeycodeToKeysym(xdisplay, key, 0); | |
| 660 if (keysym == 0 || keysym == NoSymbol) | |
| 661 { | |
| 662 keytext = g_strdup_printf("#%d", key); | |
| 663 } else { | |
| 664 keytext = g_strdup(XKeysymToString(keysym)); | |
| 665 } | |
| 666 } | |
| 667 if (type == TYPE_MOUSE) | |
| 668 { | |
| 669 keytext = g_strdup_printf("Button%d", key); | |
| 670 } | |
| 671 | |
| 672 for (i = 0, j=0; j<7; j++) | |
| 673 { | |
| 674 if (mask & modifiers[j]) | |
| 675 strings[i++] = modifier_string[j]; | |
| 676 } | |
| 677 if (key != 0) strings[i++] = keytext; | |
| 678 strings[i] = NULL; | |
| 679 | |
| 680 text = g_strjoinv(" + ", strings); | |
| 681 g_free(keytext); | |
| 682 } | |
| 683 | |
| 684 gtk_entry_set_text(GTK_ENTRY(entry), text); | |
| 685 gtk_editable_set_position(GTK_EDITABLE(entry), -1); | |
| 686 if (text) g_free(text); | |
| 687 } | |
| 688 | |
| 689 static gboolean | |
| 690 on_entry_key_press_event(GtkWidget * widget, | |
| 691 GdkEventKey * event, | |
| 692 gpointer user_data) | |
| 693 { | |
| 694 KeyControls *controls = (KeyControls*) user_data; | |
| 695 int is_mod; | |
| 696 int mod; | |
| 697 | |
| 698 if (event->keyval == GDK_Tab) return FALSE; | |
| 699 | |
| 700 mod = 0; | |
| 701 is_mod = 0; | |
| 702 | |
| 703 if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) | |
| 704 mod |= ControlMask; | |
| 705 | |
| 706 if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) | |
| 707 mod |= Mod1Mask; | |
| 708 | |
| 709 if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) | |
| 710 mod |= ShiftMask; | |
| 711 | |
| 712 if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) | |
| 713 mod |= Mod5Mask; | |
| 714 | |
| 715 if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) | |
| 716 mod |= Mod4Mask; | |
| 717 | |
| 718 if (!is_mod) { | |
| 719 controls->hotkey.key = event->hardware_keycode; | |
| 720 controls->hotkey.mask = mod; | |
| 721 controls->hotkey.type = TYPE_KEY; | |
| 722 } else controls->hotkey.key = 0; | |
| 723 | |
| 724 set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); | |
| 725 return TRUE; | |
| 726 } | |
| 727 | |
| 728 static gboolean | |
| 729 on_entry_key_release_event(GtkWidget * widget, | |
| 730 GdkEventKey * event, | |
| 731 gpointer user_data) | |
| 732 { | |
| 733 KeyControls *controls = (KeyControls*) user_data; | |
| 734 if (controls->hotkey.key == 0) { | |
| 735 controls->hotkey.mask = 0; | |
| 736 return TRUE; | |
| 737 } | |
| 738 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); | |
| 739 return TRUE; | |
| 740 } | |
| 741 | |
| 742 static gboolean | |
| 743 on_entry_button_press_event(GtkWidget * widget, | |
| 744 GdkEventButton * event, | |
| 745 gpointer user_data) | |
| 746 { | |
| 747 KeyControls *controls = (KeyControls*) user_data; | |
| 748 int mod; | |
| 749 | |
| 750 if (!gtk_widget_is_focus(widget)) return FALSE; | |
| 751 | |
| 752 mod = 0; | |
| 753 if (event->state & GDK_CONTROL_MASK) | |
| 754 mod |= ControlMask; | |
| 755 | |
| 756 if (event->state & GDK_MOD1_MASK) | |
| 757 mod |= Mod1Mask; | |
| 758 | |
| 759 if (event->state & GDK_SHIFT_MASK) | |
| 760 mod |= ShiftMask; | |
| 761 | |
| 762 if (event->state & GDK_MOD5_MASK) | |
| 763 mod |= Mod5Mask; | |
| 764 | |
| 765 if (event->state & GDK_MOD4_MASK) | |
| 766 mod |= Mod4Mask; | |
| 767 | |
| 768 if ((event->button <= 3) && (mod == 0)) | |
| 769 { | |
| 770 GtkWidget* dialog; | |
| 771 GtkResponseType response; | |
| 772 dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)), | |
| 773 GTK_DIALOG_MODAL, | |
| 774 GTK_MESSAGE_WARNING, | |
| 775 GTK_BUTTONS_YES_NO, | |
| 776 _("It is not recommended to bind the primary mouse buttons without modificators.\n\n" | |
| 777 "Do you want to continue?")); | |
| 778 gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); | |
| 779 response = gtk_dialog_run(GTK_DIALOG(dialog)); | |
| 780 gtk_widget_destroy (dialog); | |
| 781 if (response != GTK_RESPONSE_YES) return TRUE; | |
| 782 } | |
| 783 | |
| 784 controls->hotkey.key = event->button; | |
| 785 controls->hotkey.mask = mod; | |
| 786 controls->hotkey.type = TYPE_MOUSE; | |
| 787 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); | |
| 788 return TRUE; | |
| 789 } | |
| 790 | |
| 791 static gboolean | |
| 792 on_entry_scroll_event(GtkWidget * widget, | |
| 793 GdkEventScroll * event, | |
| 794 gpointer user_data) | |
| 795 { | |
| 796 KeyControls *controls = (KeyControls*) user_data; | |
| 797 int mod; | |
| 798 | |
| 799 if (!gtk_widget_is_focus(widget)) return FALSE; | |
| 800 | |
| 801 mod = 0; | |
| 802 if (event->state & GDK_CONTROL_MASK) | |
| 803 mod |= ControlMask; | |
| 804 | |
| 805 if (event->state & GDK_MOD1_MASK) | |
| 806 mod |= Mod1Mask; | |
| 807 | |
| 808 if (event->state & GDK_SHIFT_MASK) | |
| 809 mod |= ShiftMask; | |
| 810 | |
| 811 if (event->state & GDK_MOD5_MASK) | |
| 812 mod |= Mod5Mask; | |
| 813 | |
| 814 if (event->state & GDK_MOD4_MASK) | |
| 815 mod |= Mod4Mask; | |
| 816 | |
| 817 if (event->direction == GDK_SCROLL_UP) | |
| 818 controls->hotkey.key = 4; | |
| 819 else if (event->direction == GDK_SCROLL_DOWN) | |
| 820 controls->hotkey.key = 5; | |
| 821 else if (event->direction == GDK_SCROLL_LEFT) | |
| 822 controls->hotkey.key = 6; | |
| 823 else if (event->direction == GDK_SCROLL_RIGHT) | |
| 824 controls->hotkey.key = 7; | |
| 825 else return FALSE; | |
| 826 | |
| 827 controls->hotkey.mask = mod; | |
| 828 controls->hotkey.type = TYPE_MOUSE; | |
| 829 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); | |
| 830 return TRUE; | |
| 831 } | |
| 832 | |
| 833 static void add_event_controls(GtkWidget *table, | |
| 834 KeyControls *controls, | |
| 835 int row, | |
| 836 char* descr, | |
| 837 char* tooltip, | |
| 838 HotkeyConfiguration hotkey) | |
| 839 { | |
| 840 GtkWidget *label; | |
| 841 GtkWidget *button; | |
| 842 | |
| 843 controls->hotkey.key = hotkey.key; | |
| 844 controls->hotkey.mask = hotkey.mask; | |
| 845 controls->hotkey.type = hotkey.type; | |
| 846 if (controls->hotkey.key == 0) | |
| 847 controls->hotkey.mask = 0; | |
| 848 | |
| 849 label = gtk_label_new (_(descr)); | |
| 850 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, | |
| 851 (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); | |
| 852 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); | |
| 853 gtk_misc_set_padding (GTK_MISC (label), 3, 3); | |
| 854 | |
| 855 controls->keytext = gtk_entry_new (); | |
| 856 gtk_table_attach (GTK_TABLE (table), controls->keytext, 1, 2, row, row+1, | |
| 857 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0); | |
| 858 gtk_entry_set_editable (GTK_ENTRY (controls->keytext), FALSE); | |
| 859 | |
| 860 set_keytext(controls->keytext, hotkey.key, hotkey.mask, hotkey.type); | |
| 861 g_signal_connect((gpointer)controls->keytext, "key_press_event", | |
| 862 G_CALLBACK(on_entry_key_press_event), controls); | |
| 863 g_signal_connect((gpointer)controls->keytext, "key_release_event", | |
| 864 G_CALLBACK(on_entry_key_release_event), controls); | |
| 865 g_signal_connect((gpointer)controls->keytext, "button_press_event", | |
| 866 G_CALLBACK(on_entry_button_press_event), controls); | |
| 867 g_signal_connect((gpointer)controls->keytext, "scroll_event", | |
| 868 G_CALLBACK(on_entry_scroll_event), controls); | |
| 869 | |
| 870 button = gtk_button_new_with_label (_("None")); | |
| 871 gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); | |
| 872 g_signal_connect (G_OBJECT (button), "clicked", | |
| 873 G_CALLBACK (clear_keyboard), controls); | |
| 874 | |
| 875 if (tooltip != NULL) { | |
| 876 GtkTooltips *tip = gtk_tooltips_new(); | |
| 877 gtk_tooltips_set_tip(tip, controls->keytext, tooltip, NULL); | |
| 878 gtk_tooltips_set_tip(tip, button, tooltip, NULL); | |
| 879 gtk_tooltips_set_tip(tip, label, tooltip, NULL); | |
| 880 } | |
| 881 } | |
| 882 | |
| 883 /* configuration window */ | |
| 884 static void configure (void) | |
| 885 { | |
| 886 ConfigurationControls *controls; | |
| 887 GtkWidget *window; | |
| 888 GtkWidget *main_vbox, *vbox; | |
| 889 GtkWidget *hbox; | |
| 890 GtkWidget *alignment; | |
| 891 GtkWidget *frame; | |
| 892 GtkWidget *label; | |
| 893 GtkWidget *image; | |
| 894 GtkWidget *table; | |
| 895 GtkWidget *button_box, *button; | |
| 896 | |
| 897 if (!xdisplay) x_display_init(); | |
| 898 | |
| 899 load_config ( ); | |
| 900 | |
| 901 ungrab_keys(); | |
| 902 | |
| 903 controls = (ConfigurationControls*)g_malloc(sizeof(ConfigurationControls)); | |
| 904 if (!controls) | |
| 905 { | |
| 906 printf ("Faild to allocate memory for ConfigurationControls structure!\n" | |
| 907 "Aborting!"); | |
| 908 return; | |
| 909 } | |
| 910 | |
| 911 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | |
| 912 gtk_window_set_title (GTK_WINDOW (window), _("Global Hotkey Plugin Configuration")); | |
| 913 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ALWAYS); | |
| 914 gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); | |
| 915 gtk_window_set_resizable (GTK_WINDOW (window), FALSE); | |
| 916 gtk_container_set_border_width (GTK_CONTAINER (window), 5); | |
| 917 | |
| 918 main_vbox = gtk_vbox_new (FALSE, 4); | |
| 919 gtk_container_add (GTK_CONTAINER (window), main_vbox); | |
| 920 | |
| 921 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
| 922 gtk_box_pack_start (GTK_BOX (main_vbox), alignment, FALSE, TRUE, 0); | |
| 923 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); | |
| 924 hbox = gtk_hbox_new (FALSE, 2); | |
| 925 gtk_container_add (GTK_CONTAINER (alignment), hbox); | |
| 926 image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); | |
| 927 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); | |
| 928 label = gtk_label_new (_("Press a key combination inside a text field.")); | |
| 929 gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); | |
| 930 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); | |
| 931 | |
| 932 label = gtk_label_new (NULL); | |
| 933 gtk_label_set_markup (GTK_LABEL (label), _("<b>Playback:</b>")); | |
| 934 frame = gtk_frame_new (NULL); | |
| 935 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
| 936 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
| 937 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
| 938 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
| 939 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
| 940 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
| 941 vbox = gtk_vbox_new (FALSE, 2); | |
| 942 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
| 943 label = gtk_label_new (NULL); | |
| 944 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
| 945 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
| 946 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
| 947 gtk_label_set_markup (GTK_LABEL (label), | |
| 948 _("<i>Configure keys which controls Audacious playback.</i>")); | |
| 949 table = gtk_table_new (4, 3, FALSE); | |
| 950 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
| 951 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
| 952 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
| 953 | |
| 954 /* prev track */ | |
| 955 add_event_controls(table, &controls->prev_track, 0, _("Previous Track:"), NULL, | |
| 956 plugin_cfg.prev_track); | |
| 957 | |
| 958 add_event_controls(table, &controls->play, 1, _("Play:"), NULL, | |
| 959 plugin_cfg.play); | |
| 960 | |
| 961 add_event_controls(table, &controls->pause, 2, _("Pause/Resume:"), NULL, | |
| 962 plugin_cfg.pause); | |
| 963 | |
| 964 add_event_controls(table, &controls->stop, 3, _("Stop:"), NULL, | |
| 965 plugin_cfg.stop); | |
| 966 | |
| 967 add_event_controls(table, &controls->next_track, 4, _("Next Track:"), NULL, | |
| 968 plugin_cfg.next_track); | |
| 969 | |
| 970 add_event_controls(table, &controls->forward, 5, _("Forward 5 sec.:"), NULL, | |
| 971 plugin_cfg.forward); | |
| 972 | |
| 973 add_event_controls(table, &controls->backward, 6, _("Rewind 5 sec.:"), NULL, | |
| 974 plugin_cfg.backward); | |
| 975 | |
| 976 | |
| 977 label = gtk_label_new (NULL); | |
| 978 gtk_label_set_markup (GTK_LABEL (label), _("<b>Volume Control:</b>")); | |
| 979 frame = gtk_frame_new (NULL); | |
| 980 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
| 981 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
| 982 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
| 983 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
| 984 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
| 985 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
| 986 vbox = gtk_vbox_new (FALSE, 2); | |
| 987 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
| 988 label = gtk_label_new (NULL); | |
| 989 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
| 990 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
| 991 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
| 992 gtk_label_set_markup (GTK_LABEL (label), | |
| 993 _("<i>Configure keys which controls music volume.</i>")); | |
| 994 table = gtk_table_new (3, 3, FALSE); | |
| 995 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
| 996 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
| 997 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
| 998 | |
| 999 add_event_controls(table, &controls->mute, 0, _("Mute:"),NULL, | |
| 1000 plugin_cfg.mute); | |
| 1001 | |
| 1002 add_event_controls(table, &controls->vol_up, 1, _("Volume Up:"), NULL, | |
| 1003 plugin_cfg.vol_up); | |
| 1004 | |
| 1005 add_event_controls(table, &controls->vol_down, 2, _("Volume Down:"), NULL, | |
| 1006 plugin_cfg.vol_down); | |
| 1007 | |
| 1008 | |
| 1009 label = gtk_label_new (NULL); | |
| 1010 gtk_label_set_markup (GTK_LABEL (label), _("<b>Player:</b>")); | |
| 1011 frame = gtk_frame_new (NULL); | |
| 1012 gtk_frame_set_label_widget (GTK_FRAME (frame), label); | |
| 1013 gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); | |
| 1014 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); | |
| 1015 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); | |
| 1016 gtk_container_add (GTK_CONTAINER (frame), alignment); | |
| 1017 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); | |
| 1018 vbox = gtk_vbox_new (FALSE, 2); | |
| 1019 gtk_container_add (GTK_CONTAINER (alignment), vbox); | |
| 1020 label = gtk_label_new (NULL); | |
| 1021 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); | |
| 1022 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); | |
| 1023 gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); | |
| 1024 gtk_label_set_markup (GTK_LABEL (label), | |
| 1025 _("<i>Configure keys which control the player.</i>")); | |
| 1026 table = gtk_table_new (3, 3, FALSE); | |
| 1027 gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); | |
| 1028 gtk_table_set_col_spacings (GTK_TABLE (table), 2); | |
| 1029 gtk_table_set_row_spacings (GTK_TABLE (table), 2); | |
| 1030 | |
| 1031 add_event_controls(table, &controls->jump_to_file, 0, _("Jump to File:"), NULL, | |
| 1032 plugin_cfg.jump_to_file); | |
| 1033 | |
| 1034 add_event_controls(table, &controls->toggle_win, 1, _("Toggle Player Windows:"), NULL, | |
| 1035 plugin_cfg.toggle_win); | |
| 1036 | |
| 1037 add_event_controls(table, &controls->show_aosd, 2, _("Show On-Screen-Display:"), | |
| 1038 _("For this, the Audacious OSD plugin must be activated."), | |
| 1039 plugin_cfg.show_aosd); | |
| 1040 | |
| 1041 button_box = gtk_hbutton_box_new ( ); | |
| 1042 gtk_box_pack_start (GTK_BOX (main_vbox), button_box, FALSE, TRUE, 6); | |
| 1043 gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END); | |
| 1044 gtk_box_set_spacing (GTK_BOX (button_box), 4); | |
| 1045 | |
| 1046 button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); | |
| 1047 gtk_container_add (GTK_CONTAINER (button_box), button); | |
| 1048 g_signal_connect (G_OBJECT (button), "clicked", | |
| 1049 G_CALLBACK (cancel_callback), controls); | |
| 1050 | |
| 1051 button = gtk_button_new_from_stock (GTK_STOCK_OK); | |
| 1052 gtk_container_add (GTK_CONTAINER (button_box), button); | |
| 1053 g_signal_connect (G_OBJECT (button), "clicked", | |
| 1054 G_CALLBACK (ok_callback), controls); | |
| 1055 | |
| 1056 gtk_widget_show_all (GTK_WIDGET (window)); | |
| 1057 } | |
| 1058 /* configuration window end */ | |
| 1059 | |
| 1060 static void about (void) | |
| 1061 { | |
| 1062 static GtkWidget *dialog; | |
| 1063 | |
| 1064 dialog = audacious_info_dialog (_("About Global Hotkey Plugin"), | |
| 1065 _("Global Hotkey Plugin\n" | |
| 1066 "Control the player with global key combinations or multimedia keys.\n\n" | |
| 1067 "Copyright (C) 2007-2008 Sascha Hlusiak <contact@saschahlusiak.de>\n\n" | |
| 1068 "Contributers include:\n" | |
| 1069 "Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov@gmail.com>\n" | |
| 1070 "Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi>\n" | |
| 1071 " Bryn Davies <curious@ihug.com.au>\n" | |
| 1072 " Jonathan A. Davis <davis@jdhouse.org>\n" | |
| 1073 " Jeremy Tan <nsx@nsx.homeip.net>\n\n" | |
| 1074 ), | |
| 1075 _("OK"), TRUE, NULL, NULL); | |
| 1076 | |
| 1077 gtk_signal_connect(GTK_OBJECT(dialog), "destroy", | |
| 1078 GTK_SIGNAL_FUNC(gtk_widget_destroyed), &dialog); | |
| 1079 } | |
| 1080 | |
| 1081 /* Clear keys */ | |
| 1082 static void clear_keyboard (GtkWidget *widget, gpointer data) | |
| 1083 { | |
| 1084 KeyControls *spins = (KeyControls*)data; | |
| 1085 spins->hotkey.key = 0; | |
| 1086 spins->hotkey.mask = 0; | |
| 1087 spins->hotkey.type = TYPE_KEY; | |
| 1088 set_keytext(spins->keytext, 0, 0, TYPE_KEY); | |
| 1089 } | |
| 1090 | |
| 1091 void cancel_callback (GtkWidget *widget, gpointer data) | |
| 1092 { | |
| 1093 if (loaded) | |
| 1094 { | |
| 1095 grab_keys (); | |
| 1096 } | |
| 1097 if (data) g_free(data); | |
| 1098 | |
| 1099 gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); | |
| 1100 } | |
| 1101 | |
| 1102 void ok_callback (GtkWidget *widget, gpointer data) | |
| 1103 { | |
| 1104 ConfigurationControls *controls= (ConfigurationControls*)data; | |
| 1105 | |
| 1106 plugin_cfg.play = controls->play.hotkey; | |
| 1107 plugin_cfg.pause = controls->pause.hotkey; | |
| 1108 plugin_cfg.stop= controls->stop.hotkey; | |
| 1109 plugin_cfg.prev_track= controls->prev_track.hotkey; | |
| 1110 plugin_cfg.next_track = controls->next_track.hotkey; | |
| 1111 plugin_cfg.forward = controls->forward.hotkey; | |
| 1112 plugin_cfg.backward = controls->backward.hotkey; | |
| 1113 plugin_cfg.vol_up= controls->vol_up.hotkey; | |
| 1114 plugin_cfg.vol_down = controls->vol_down.hotkey; | |
| 1115 plugin_cfg.mute = controls->mute.hotkey; | |
| 1116 plugin_cfg.jump_to_file= controls->jump_to_file.hotkey; | |
| 1117 plugin_cfg.toggle_win = controls->toggle_win.hotkey; | |
| 1118 plugin_cfg.show_aosd = controls->show_aosd.hotkey; | |
| 1119 | |
| 1120 save_config ( ); | |
| 1121 | |
| 1122 if (loaded) | |
| 1123 { | |
| 1124 grab_keys (); | |
| 1125 } | |
| 1126 | |
| 1127 if (data) g_free(data); | |
| 1128 | |
| 1129 gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); | |
| 1130 } | |
| 1131 | |
| 1132 /* | |
| 1133 * plugin cleanup | |
| 1134 */ | |
| 1135 static void cleanup (void) | 342 static void cleanup (void) |
| 1136 { | 343 { |
| 1137 if (!loaded) return; | 344 if (!loaded) return; |
| 1138 ungrab_keys (); | 345 ungrab_keys (); |
| 1139 release_filter(); | 346 release_filter(); |
| 1140 loaded = FALSE; | 347 loaded = FALSE; |
| 1141 } | 348 } |
| 1142 | 349 |
| 1143 /* grab required keys */ | 350 gboolean is_loaded (void) |
| 1144 static void ungrab_key(HotkeyConfiguration hotkey) | 351 { |
| 1145 { | 352 return loaded; |
| 1146 unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); | 353 } |
| 1147 | |
| 1148 if (hotkey.key == 0) return; | |
| 1149 | |
| 1150 if (hotkey.type == TYPE_KEY) | |
| 1151 { | |
| 1152 XUngrabKey (xdisplay, hotkey.key, modifier, x_root_window); | |
| 1153 | |
| 1154 if (modifier == AnyModifier) | |
| 1155 return; | |
| 1156 | |
| 1157 if (numlock_mask) | |
| 1158 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); | |
| 1159 | |
| 1160 if (capslock_mask) | |
| 1161 XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); | |
| 1162 | |
| 1163 if (scrolllock_mask) | |
| 1164 XUngrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); | |
| 1165 | |
| 1166 if (numlock_mask && capslock_mask) | |
| 1167 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); | |
| 1168 | |
| 1169 if (numlock_mask && scrolllock_mask) | |
| 1170 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); | |
| 1171 | |
| 1172 if (capslock_mask && scrolllock_mask) | |
| 1173 XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); | |
| 1174 | |
| 1175 if (numlock_mask && capslock_mask && scrolllock_mask) | |
| 1176 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); | |
| 1177 } | |
| 1178 if (hotkey.type == TYPE_MOUSE) | |
| 1179 { | |
| 1180 XUngrabButton (xdisplay, hotkey.key, modifier, x_root_window); | |
| 1181 | |
| 1182 if (modifier == AnyModifier) | |
| 1183 return; | |
| 1184 | |
| 1185 if (numlock_mask) | |
| 1186 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); | |
| 1187 | |
| 1188 if (capslock_mask) | |
| 1189 XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); | |
| 1190 | |
| 1191 if (scrolllock_mask) | |
| 1192 XUngrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); | |
| 1193 | |
| 1194 if (numlock_mask && capslock_mask) | |
| 1195 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); | |
| 1196 | |
| 1197 if (numlock_mask && scrolllock_mask) | |
| 1198 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); | |
| 1199 | |
| 1200 if (capslock_mask && scrolllock_mask) | |
| 1201 XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); | |
| 1202 | |
| 1203 if (numlock_mask && capslock_mask && scrolllock_mask) | |
| 1204 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); | |
| 1205 } | |
| 1206 } | |
| 1207 | |
| 1208 static void ungrab_keys () | |
| 1209 { | |
| 1210 XErrorHandler old_handler = 0; | |
| 1211 | |
| 1212 if (!grabbed) return; | |
| 1213 if (!xdisplay) return; | |
| 1214 | |
| 1215 XSync(xdisplay, False); | |
| 1216 old_handler = XSetErrorHandler (x11_error_handler); | |
| 1217 | |
| 1218 ungrab_key(plugin_cfg.mute); | |
| 1219 ungrab_key(plugin_cfg.vol_up); | |
| 1220 ungrab_key(plugin_cfg.vol_down); | |
| 1221 ungrab_key(plugin_cfg.play); | |
| 1222 ungrab_key(plugin_cfg.pause); | |
| 1223 ungrab_key(plugin_cfg.stop); | |
| 1224 ungrab_key(plugin_cfg.prev_track); | |
| 1225 ungrab_key(plugin_cfg.next_track); | |
| 1226 ungrab_key(plugin_cfg.jump_to_file); | |
| 1227 ungrab_key(plugin_cfg.forward); | |
| 1228 ungrab_key(plugin_cfg.backward); | |
| 1229 ungrab_key(plugin_cfg.toggle_win); | |
| 1230 ungrab_key(plugin_cfg.show_aosd); | |
| 1231 | |
| 1232 XSync(xdisplay, False); | |
| 1233 XSetErrorHandler (old_handler); | |
| 1234 | |
| 1235 grabbed = 0; | |
| 1236 } |
