comparison src/hotkey/plugin.c @ 2274:d9706e29e968

Hotkey: Added grabbing of mouse buttons with modificators so you can control it with the mouse from any application
author Sascha Hlusiak <contact@saschahlusiak.de>
date Mon, 31 Dec 2007 19:45:28 +0100
parents f893d05f707b
children 6ca0d83ce51d
comparison
equal deleted inserted replaced
2273:f893d05f707b 2274:d9706e29e968
59 void x_display_init (void); 59 void x_display_init (void);
60 static void get_offending_modifiers (Display * dpy); 60 static void get_offending_modifiers (Display * dpy);
61 static void init (void); 61 static void init (void);
62 static void grab_keys (); 62 static void grab_keys ();
63 static void ungrab_keys (); 63 static void ungrab_keys ();
64 static gboolean handle_keyevent(int keycode, int state); 64 static gboolean handle_keyevent(int keycode, int state, int type);
65 static gboolean setup_filter(); 65 static gboolean setup_filter();
66 static void release_filter(); 66 static void release_filter();
67 67
68 static void load_config (void); 68 static void load_config (void);
69 static void save_config (void); 69 static void save_config (void);
207 if (modmap) 207 if (modmap)
208 XFreeModifiermap (modmap); 208 XFreeModifiermap (modmap);
209 } 209 }
210 210
211 /* handle keys */ 211 /* handle keys */
212 static gboolean handle_keyevent (int keycode, int state) 212 static gboolean handle_keyevent (int keycode, int state, int type)
213 { 213 {
214 gint current_volume, old_volume; 214 gint current_volume, old_volume;
215 static gint volume_static = 0; 215 static gint volume_static = 0;
216 gboolean play, mute; 216 gboolean play, mute;
217 217
231 } 231 }
232 232
233 state &= ~(scrolllock_mask | numlock_mask | capslock_mask); 233 state &= ~(scrolllock_mask | numlock_mask | capslock_mask);
234 234
235 /* mute the playback */ 235 /* mute the playback */
236 if ((keycode == plugin_cfg.mute.key) && (state == plugin_cfg.mute.mask)) 236 if ((keycode == plugin_cfg.mute.key) && (state == plugin_cfg.mute.mask) && (type == plugin_cfg.mute.type))
237 { 237 {
238 if (!mute) 238 if (!mute)
239 { 239 {
240 volume_static = current_volume; 240 volume_static = current_volume;
241 audacious_drct_set_main_volume (0); 241 audacious_drct_set_main_volume (0);
246 } 246 }
247 return TRUE; 247 return TRUE;
248 } 248 }
249 249
250 /* decreace volume */ 250 /* decreace volume */
251 if ((keycode == plugin_cfg.vol_down.key) && (state == plugin_cfg.vol_down.mask)) 251 if ((keycode == plugin_cfg.vol_down.key) && (state == plugin_cfg.vol_down.mask) && (type == plugin_cfg.vol_down.type))
252 { 252 {
253 if (mute) 253 if (mute)
254 { 254 {
255 current_volume = old_volume; 255 current_volume = old_volume;
256 old_volume = 0; 256 old_volume = 0;
270 old_volume = current_volume; 270 old_volume = current_volume;
271 return TRUE; 271 return TRUE;
272 } 272 }
273 273
274 /* increase volume */ 274 /* increase volume */
275 if ((keycode == plugin_cfg.vol_up.key) && (state == plugin_cfg.vol_up.mask)) 275 if ((keycode == plugin_cfg.vol_up.key) && (state == plugin_cfg.vol_up.mask) && (type == plugin_cfg.vol_up.type))
276 { 276 {
277 if (mute) 277 if (mute)
278 { 278 {
279 current_volume = old_volume; 279 current_volume = old_volume;
280 old_volume = 0; 280 old_volume = 0;
294 old_volume = current_volume; 294 old_volume = current_volume;
295 return TRUE; 295 return TRUE;
296 } 296 }
297 297
298 /* play */ 298 /* play */
299 if ((keycode == plugin_cfg.play.key) && (state == plugin_cfg.play.mask)) 299 if ((keycode == plugin_cfg.play.key) && (state == plugin_cfg.play.mask) && (type == plugin_cfg.play.type))
300 { 300 {
301 if (!play) 301 if (!play)
302 { 302 {
303 audacious_drct_play (); 303 audacious_drct_play ();
304 } else { 304 } else {
306 } 306 }
307 return TRUE; 307 return TRUE;
308 } 308 }
309 309
310 /* pause */ 310 /* pause */
311 if ((keycode == plugin_cfg.pause.key) && (state == plugin_cfg.pause.mask)) 311 if ((keycode == plugin_cfg.pause.key) && (state == plugin_cfg.pause.mask) && (type == plugin_cfg.pause.type))
312 { 312 {
313 if (!play) audacious_drct_play (); 313 if (!play) audacious_drct_play ();
314 else audacious_drct_pause (); 314 else audacious_drct_pause ();
315 315
316 return TRUE; 316 return TRUE;
317 } 317 }
318 318
319 /* stop */ 319 /* stop */
320 if ((keycode == plugin_cfg.stop.key) && (state == plugin_cfg.stop.mask)) 320 if ((keycode == plugin_cfg.stop.key) && (state == plugin_cfg.stop.mask) && (type == plugin_cfg.stop.type))
321 { 321 {
322 audacious_drct_stop (); 322 audacious_drct_stop ();
323 return TRUE; 323 return TRUE;
324 } 324 }
325 325
326 /* prev track */ 326 /* prev track */
327 if ((keycode == plugin_cfg.prev_track.key) && (state == plugin_cfg.prev_track.mask)) 327 if ((keycode == plugin_cfg.prev_track.key) && (state == plugin_cfg.prev_track.mask) && (type == plugin_cfg.prev_track.type))
328 { 328 {
329 audacious_drct_playlist_prev (); 329 audacious_drct_playlist_prev ();
330 return TRUE; 330 return TRUE;
331 } 331 }
332 332
333 /* next track */ 333 /* next track */
334 if ((keycode == plugin_cfg.next_track.key) && (state == plugin_cfg.next_track.mask)) 334 if ((keycode == plugin_cfg.next_track.key) && (state == plugin_cfg.next_track.mask) && (type == plugin_cfg.next_track.type))
335 { 335 {
336 audacious_drct_playlist_next (); 336 audacious_drct_playlist_next ();
337 return TRUE; 337 return TRUE;
338 } 338 }
339 339
340 /* forward */ 340 /* forward */
341 if ((keycode == plugin_cfg.forward.key) && (state == plugin_cfg.forward.mask)) 341 if ((keycode == plugin_cfg.forward.key) && (state == plugin_cfg.forward.mask) && (type == plugin_cfg.forward.type))
342 { 342 {
343 gint time = audacious_drct_get_output_time(); 343 gint time = audacious_drct_get_output_time();
344 time += 5000; /* Jump 5s into future */ 344 time += 5000; /* Jump 5s into future */
345 audacious_drct_jump_to_time(time); 345 audacious_drct_jump_to_time(time);
346 return TRUE; 346 return TRUE;
347 } 347 }
348 348
349 /* backward */ 349 /* backward */
350 if ((keycode == plugin_cfg.backward.key) && (state == plugin_cfg.backward.mask)) 350 if ((keycode == plugin_cfg.backward.key) && (state == plugin_cfg.backward.mask) && (type == plugin_cfg.backward.type))
351 { 351 {
352 gint time = audacious_drct_get_output_time(); 352 gint time = audacious_drct_get_output_time();
353 if (time > 5000) time -= 5000; /* Jump 5s back */ 353 if (time > 5000) time -= 5000; /* Jump 5s back */
354 else time = 0; 354 else time = 0;
355 audacious_drct_jump_to_time(time); 355 audacious_drct_jump_to_time(time);
356 return TRUE; 356 return TRUE;
357 } 357 }
358 358
359 /* Open Jump-To-File dialog */ 359 /* Open Jump-To-File dialog */
360 if ((keycode == plugin_cfg.jump_to_file.key) && (state == plugin_cfg.jump_to_file.mask)) 360 if ((keycode == plugin_cfg.jump_to_file.key) && (state == plugin_cfg.jump_to_file.mask) && (type == plugin_cfg.jump_to_file.type))
361 { 361 {
362 audacious_drct_show_jtf_box(); 362 audacious_drct_show_jtf_box();
363 return TRUE; 363 return TRUE;
364 } 364 }
365 365
366 /* Toggle Windows */ 366 /* Toggle Windows */
367 if ((keycode == plugin_cfg.toggle_win.key) && (state == plugin_cfg.toggle_win.mask)) 367 if ((keycode == plugin_cfg.toggle_win.key) && (state == plugin_cfg.toggle_win.mask) && (type == plugin_cfg.toggle_win.type))
368 { 368 {
369 static gboolean is_main, is_eq, is_pl; 369 static gboolean is_main, is_eq, is_pl;
370 is_main = audacious_drct_main_win_is_visible(); 370 is_main = audacious_drct_main_win_is_visible();
371 if (is_main) { 371 if (is_main) {
372 is_pl = audacious_drct_pl_win_is_visible(); 372 is_pl = audacious_drct_pl_win_is_visible();
388 static GdkFilterReturn 388 static GdkFilterReturn
389 gdk_filter(GdkXEvent *xevent, 389 gdk_filter(GdkXEvent *xevent,
390 GdkEvent *event, 390 GdkEvent *event,
391 gpointer data) 391 gpointer data)
392 { 392 {
393 XKeyEvent *keyevent = (XKeyEvent*)xevent; 393 switch (((XEvent*)xevent)->type)
394 394 {
395 if (((XEvent*)keyevent)->type != KeyPress) 395 case KeyPress:
396 {
397 XKeyEvent *keyevent = (XKeyEvent*)xevent;
398 if (handle_keyevent(keyevent->keycode, keyevent->state, TYPE_KEY))
399 return GDK_FILTER_REMOVE;
400 break;
401 }
402 case ButtonPress:
403 {
404 XButtonEvent *buttonevent = (XButtonEvent*)xevent;
405 if (handle_keyevent(buttonevent->button, buttonevent->state, TYPE_MOUSE))
406 return GDK_FILTER_REMOVE;
407 break;
408 }
409 default:
396 return -1; 410 return -1;
397 411 }
398 if (handle_keyevent(keyevent->keycode, keyevent->state))
399 return GDK_FILTER_REMOVE;
400 412
401 return GDK_FILTER_CONTINUE; 413 return GDK_FILTER_CONTINUE;
402 } 414 }
403 415
404 static gboolean 416 static gboolean
489 static int x11_error_handler (Display *dpy, XErrorEvent *error) 501 static int x11_error_handler (Display *dpy, XErrorEvent *error)
490 { 502 {
491 return 0; 503 return 0;
492 } 504 }
493 505
494 /* grab requied keys */ 506 /* grab required keys */
495 static void grab_key(HotkeyConfiguration hotkey) 507 static void grab_key(HotkeyConfiguration hotkey)
496 { 508 {
497 unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); 509 unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
498 510
499 if (hotkey.key == 0) return; 511 if (hotkey.key == 0) return;
500 512
501 XGrabKey (xdisplay, hotkey.key, modifier, x_root_window, 513 if (hotkey.type == TYPE_KEY)
502 False, GrabModeAsync, GrabModeAsync); 514 {
503 515 XGrabKey (xdisplay, hotkey.key, modifier, x_root_window,
504 if (modifier == AnyModifier)
505 return;
506
507 if (numlock_mask)
508 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask,
509 x_root_window,
510 False, GrabModeAsync, GrabModeAsync); 516 False, GrabModeAsync, GrabModeAsync);
511 517
512 if (capslock_mask) 518 if (modifier == AnyModifier)
513 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask, 519 return;
514 x_root_window, 520
515 False, GrabModeAsync, GrabModeAsync); 521 if (numlock_mask)
516 522 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask,
517 if (scrolllock_mask) 523 x_root_window,
518 XGrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, 524 False, GrabModeAsync, GrabModeAsync);
519 x_root_window, 525
520 False, GrabModeAsync, GrabModeAsync); 526 if (capslock_mask)
521 527 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask,
522 if (numlock_mask && capslock_mask) 528 x_root_window,
523 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, 529 False, GrabModeAsync, GrabModeAsync);
524 x_root_window, 530
525 False, GrabModeAsync, GrabModeAsync); 531 if (scrolllock_mask)
526 532 XGrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask,
527 if (numlock_mask && scrolllock_mask) 533 x_root_window,
528 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, 534 False, GrabModeAsync, GrabModeAsync);
529 x_root_window, 535
530 False, GrabModeAsync, GrabModeAsync); 536 if (numlock_mask && capslock_mask)
531 537 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask,
532 if (capslock_mask && scrolllock_mask) 538 x_root_window,
533 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, 539 False, GrabModeAsync, GrabModeAsync);
534 x_root_window, 540
535 False, GrabModeAsync, GrabModeAsync); 541 if (numlock_mask && scrolllock_mask)
536 542 XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask,
537 if (numlock_mask && capslock_mask && scrolllock_mask) 543 x_root_window,
538 XGrabKey (xdisplay, hotkey.key, 544 False, GrabModeAsync, GrabModeAsync);
539 modifier | numlock_mask | capslock_mask | scrolllock_mask, 545
540 x_root_window, False, GrabModeAsync, 546 if (capslock_mask && scrolllock_mask)
541 GrabModeAsync); 547 XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask,
542 } 548 x_root_window,
543 549 False, GrabModeAsync, GrabModeAsync);
550
551 if (numlock_mask && capslock_mask && scrolllock_mask)
552 XGrabKey (xdisplay, hotkey.key,
553 modifier | numlock_mask | capslock_mask | scrolllock_mask,
554 x_root_window, False, GrabModeAsync,
555 GrabModeAsync);
556 }
557 if (hotkey.type == TYPE_MOUSE)
558 {
559 XGrabButton (xdisplay, hotkey.key, modifier, x_root_window,
560 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
561
562 if (modifier == AnyModifier)
563 return;
564
565 if (numlock_mask)
566 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask,
567 x_root_window,
568 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
569
570 if (capslock_mask)
571 XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask,
572 x_root_window,
573 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
574
575 if (scrolllock_mask)
576 XGrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask,
577 x_root_window,
578 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
579
580 if (numlock_mask && capslock_mask)
581 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask,
582 x_root_window,
583 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
584
585 if (numlock_mask && scrolllock_mask)
586 XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask,
587 x_root_window,
588 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
589
590 if (capslock_mask && scrolllock_mask)
591 XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask,
592 x_root_window,
593 False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None);
594
595 if (numlock_mask && capslock_mask && scrolllock_mask)
596 XGrabButton (xdisplay, hotkey.key,
597 modifier | numlock_mask | capslock_mask | scrolllock_mask,
598 x_root_window, False, ButtonPressMask, GrabModeAsync,
599 GrabModeAsync, None, None);
600 }
601 }
544 602
545 static void grab_keys () 603 static void grab_keys ()
546 { 604 {
547 if (grabbed) return; 605 if (grabbed) return;
548 if (xdisplay == NULL) x_display_init(); 606 if (xdisplay == NULL) x_display_init();
585 static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" }; 643 static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" };
586 static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; 644 static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
587 gchar *strings[9]; 645 gchar *strings[9];
588 gchar *keytext = NULL; 646 gchar *keytext = NULL;
589 int i, j; 647 int i, j;
590 KeySym keysym; 648 if (type == TYPE_KEY)
591 649 {
592 keysym = XKeycodeToKeysym(xdisplay, key, 0); 650 KeySym keysym;
593 if (keysym == 0 || keysym == NoSymbol) 651 keysym = XKeycodeToKeysym(xdisplay, key, 0);
594 { 652 if (keysym == 0 || keysym == NoSymbol)
595 keytext = g_strdup_printf("#%3d", key); 653 {
596 } else { 654 keytext = g_strdup_printf("#%d", key);
597 keytext = g_strdup(XKeysymToString(keysym)); 655 } else {
656 keytext = g_strdup(XKeysymToString(keysym));
657 }
658 }
659 if (type == TYPE_MOUSE)
660 {
661 keytext = g_strdup_printf("Button%d", key);
598 } 662 }
599 663
600 for (i = 0, j=0; j<7; j++) 664 for (i = 0, j=0; j<7; j++)
601 { 665 {
602 if (mask & modifiers[j]) 666 if (mask & modifiers[j])
622 KeyControls *controls = (KeyControls*) user_data; 686 KeyControls *controls = (KeyControls*) user_data;
623 int is_mod; 687 int is_mod;
624 int mod; 688 int mod;
625 689
626 if (event->keyval == GDK_Tab) return FALSE; 690 if (event->keyval == GDK_Tab) return FALSE;
691
627 mod = 0; 692 mod = 0;
628 is_mod = 0; 693 is_mod = 0;
629 694
630 if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) 695 if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R))))
631 mod |= ControlMask; 696 mod |= ControlMask;
647 controls->hotkey.mask = mod; 712 controls->hotkey.mask = mod;
648 controls->hotkey.type = TYPE_KEY; 713 controls->hotkey.type = TYPE_KEY;
649 } else controls->hotkey.key = 0; 714 } else controls->hotkey.key = 0;
650 715
651 set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); 716 set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY);
652 return FALSE; 717 return TRUE;
653 } 718 }
654 719
655 static gboolean 720 static gboolean
656 on_entry_key_release_event(GtkWidget * widget, 721 on_entry_key_release_event(GtkWidget * widget,
657 GdkEventKey * event, 722 GdkEventKey * event,
658 gpointer user_data) 723 gpointer user_data)
659 { 724 {
660 KeyControls *controls = (KeyControls*) user_data; 725 KeyControls *controls = (KeyControls*) user_data;
661 if (controls->hotkey.key == 0) { 726 if (controls->hotkey.key == 0) {
662 controls->hotkey.mask = 0; 727 controls->hotkey.mask = 0;
728 return TRUE;
663 } 729 }
664 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); 730 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
665 return FALSE; 731 return TRUE;
666 } 732 }
667 733
734 static gboolean
735 on_entry_button_press_event(GtkWidget * widget,
736 GdkEventButton * event,
737 gpointer user_data)
738 {
739 KeyControls *controls = (KeyControls*) user_data;
740 int mod;
741
742 if (!gtk_widget_is_focus(widget)) return FALSE;
743
744 mod = 0;
745 if (event->state & GDK_CONTROL_MASK)
746 mod |= ControlMask;
747
748 if (event->state & GDK_MOD1_MASK)
749 mod |= Mod1Mask;
750
751 if (event->state & GDK_SHIFT_MASK)
752 mod |= ShiftMask;
753
754 if (event->state & GDK_MOD5_MASK)
755 mod |= Mod5Mask;
756
757 if (event->state & GDK_MOD4_MASK)
758 mod |= Mod4Mask;
759
760 if ((event->button <= 3) && (mod == 0))
761 {
762 GtkWidget* dialog;
763 GtkResponseType response;
764 dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)),
765 GTK_DIALOG_MODAL,
766 GTK_MESSAGE_WARNING,
767 GTK_BUTTONS_YES_NO,
768 _("It is not recommended to bind the primary mouse buttons without modificators.\n\n"
769 "Do you want to continue?"));
770 gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons"));
771 response = gtk_dialog_run(GTK_DIALOG(dialog));
772 gtk_widget_destroy (dialog);
773 if (response != GTK_RESPONSE_YES) return TRUE;
774 }
775
776 controls->hotkey.key = event->button;
777 controls->hotkey.mask = mod;
778 controls->hotkey.type = TYPE_MOUSE;
779 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
780 return TRUE;
781 }
782
783 static gboolean
784 on_entry_scroll_event(GtkWidget * widget,
785 GdkEventScroll * event,
786 gpointer user_data)
787 {
788 KeyControls *controls = (KeyControls*) user_data;
789 int mod;
790
791 if (!gtk_widget_is_focus(widget)) return FALSE;
792
793 mod = 0;
794 if (event->state & GDK_CONTROL_MASK)
795 mod |= ControlMask;
796
797 if (event->state & GDK_MOD1_MASK)
798 mod |= Mod1Mask;
799
800 if (event->state & GDK_SHIFT_MASK)
801 mod |= ShiftMask;
802
803 if (event->state & GDK_MOD5_MASK)
804 mod |= Mod5Mask;
805
806 if (event->state & GDK_MOD4_MASK)
807 mod |= Mod4Mask;
808
809 if (event->direction == GDK_SCROLL_UP)
810 controls->hotkey.key = 4;
811 else if (event->direction == GDK_SCROLL_DOWN)
812 controls->hotkey.key = 5;
813 else if (event->direction == GDK_SCROLL_LEFT)
814 controls->hotkey.key = 6;
815 else if (event->direction == GDK_SCROLL_RIGHT)
816 controls->hotkey.key = 7;
817 else return FALSE;
818
819 controls->hotkey.mask = mod;
820 controls->hotkey.type = TYPE_MOUSE;
821 set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
822 return TRUE;
823 }
668 824
669 static void add_event_controls(GtkWidget *table, 825 static void add_event_controls(GtkWidget *table,
670 KeyControls *controls, 826 KeyControls *controls,
671 int row, 827 int row,
672 char* descr, 828 char* descr,
675 GtkWidget *label; 831 GtkWidget *label;
676 GtkWidget *button; 832 GtkWidget *button;
677 833
678 controls->hotkey.key = hotkey.key; 834 controls->hotkey.key = hotkey.key;
679 controls->hotkey.mask = hotkey.mask; 835 controls->hotkey.mask = hotkey.mask;
836 controls->hotkey.type = hotkey.type;
837 if (controls->hotkey.key == 0)
838 controls->hotkey.mask = 0;
680 839
681 label = gtk_label_new (_(descr)); 840 label = gtk_label_new (_(descr));
682 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, 841 gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1,
683 (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); 842 (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
684 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); 843 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
692 set_keytext(controls->keytext, hotkey.key, hotkey.mask, hotkey.type); 851 set_keytext(controls->keytext, hotkey.key, hotkey.mask, hotkey.type);
693 g_signal_connect((gpointer)controls->keytext, "key_press_event", 852 g_signal_connect((gpointer)controls->keytext, "key_press_event",
694 G_CALLBACK(on_entry_key_press_event), controls); 853 G_CALLBACK(on_entry_key_press_event), controls);
695 g_signal_connect((gpointer)controls->keytext, "key_release_event", 854 g_signal_connect((gpointer)controls->keytext, "key_release_event",
696 G_CALLBACK(on_entry_key_release_event), controls); 855 G_CALLBACK(on_entry_key_release_event), controls);
856 g_signal_connect((gpointer)controls->keytext, "button_press_event",
857 G_CALLBACK(on_entry_button_press_event), controls);
858 g_signal_connect((gpointer)controls->keytext, "scroll_event",
859 G_CALLBACK(on_entry_scroll_event), controls);
697 860
698 button = gtk_button_new_with_label (_("None")); 861 button = gtk_button_new_with_label (_("None"));
699 gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); 862 gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
700 g_signal_connect (G_OBJECT (button), "clicked", 863 g_signal_connect (G_OBJECT (button), "clicked",
701 G_CALLBACK (clear_keyboard), controls); 864 G_CALLBACK (clear_keyboard), controls);
954 if (!loaded) return; 1117 if (!loaded) return;
955 ungrab_keys (); 1118 ungrab_keys ();
956 release_filter(); 1119 release_filter();
957 loaded = FALSE; 1120 loaded = FALSE;
958 } 1121 }
959 1122
1123 /* grab required keys */
1124 static void ungrab_key(HotkeyConfiguration hotkey)
1125 {
1126 unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask);
1127
1128 if (hotkey.key == 0) return;
1129
1130 if (hotkey.type == TYPE_KEY)
1131 {
1132 XUngrabKey (xdisplay, hotkey.key, modifier, x_root_window);
1133
1134 if (modifier == AnyModifier)
1135 return;
1136
1137 if (numlock_mask)
1138 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window);
1139
1140 if (capslock_mask)
1141 XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window);
1142
1143 if (scrolllock_mask)
1144 XUngrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window);
1145
1146 if (numlock_mask && capslock_mask)
1147 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window);
1148
1149 if (numlock_mask && scrolllock_mask)
1150 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window);
1151
1152 if (capslock_mask && scrolllock_mask)
1153 XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window);
1154
1155 if (numlock_mask && capslock_mask && scrolllock_mask)
1156 XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
1157 }
1158 if (hotkey.type == TYPE_MOUSE)
1159 {
1160 XUngrabButton (xdisplay, hotkey.key, modifier, x_root_window);
1161
1162 if (modifier == AnyModifier)
1163 return;
1164
1165 if (numlock_mask)
1166 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window);
1167
1168 if (capslock_mask)
1169 XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window);
1170
1171 if (scrolllock_mask)
1172 XUngrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window);
1173
1174 if (numlock_mask && capslock_mask)
1175 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window);
1176
1177 if (numlock_mask && scrolllock_mask)
1178 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window);
1179
1180 if (capslock_mask && scrolllock_mask)
1181 XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window);
1182
1183 if (numlock_mask && capslock_mask && scrolllock_mask)
1184 XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window);
1185 }
1186 }
1187
960 static void ungrab_keys () 1188 static void ungrab_keys ()
961 { 1189 {
1190 XErrorHandler old_handler = 0;
1191
962 if (!grabbed) return; 1192 if (!grabbed) return;
963 if (!xdisplay) return; 1193 if (!xdisplay) return;
964 1194
965 XUngrabKey (xdisplay, AnyKey, AnyModifier, x_root_window); 1195 XSync(xdisplay, False);
966 1196 old_handler = XSetErrorHandler (x11_error_handler);
1197
1198 ungrab_key(plugin_cfg.mute);
1199 ungrab_key(plugin_cfg.vol_up);
1200 ungrab_key(plugin_cfg.vol_down);
1201 ungrab_key(plugin_cfg.play);
1202 ungrab_key(plugin_cfg.pause);
1203 ungrab_key(plugin_cfg.stop);
1204 ungrab_key(plugin_cfg.prev_track);
1205 ungrab_key(plugin_cfg.next_track);
1206 ungrab_key(plugin_cfg.jump_to_file);
1207 ungrab_key(plugin_cfg.forward);
1208 ungrab_key(plugin_cfg.backward);
1209 ungrab_key(plugin_cfg.toggle_win);
1210
1211 XSync(xdisplay, False);
1212 XSetErrorHandler (old_handler);
1213
967 grabbed = 0; 1214 grabbed = 0;
968 } 1215 }