Mercurial > audlegacy-plugins
changeset 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 | 62391135da44 |
children | 5b37a9f2d0cc |
files | src/hotkey/Makefile src/hotkey/grab.c src/hotkey/grab.h src/hotkey/gui.c src/hotkey/gui.h src/hotkey/plugin.c src/hotkey/plugin.h |
diffstat | 7 files changed, 1017 insertions(+), 904 deletions(-) [+] |
line wrap: on
line diff
--- a/src/hotkey/Makefile Tue Jan 15 12:35:54 2008 +0200 +++ b/src/hotkey/Makefile Sun Jan 20 14:52:44 2008 +0100 @@ -1,6 +1,6 @@ PLUGIN = hotkey${PLUGIN_SUFFIX} -SRCS = plugin.c +SRCS = plugin.c gui.c grab.c include ../../buildsys.mk include ../../extra.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotkey/grab.c Sun Jan 20 14:52:44 2008 +0100 @@ -0,0 +1,372 @@ +/* + * This file is part of audacious-hotkey plugin for audacious + * + * Copyright (c) 2007 - 2008 Sascha Hlusiak <contact@saschahlusiak.de> + * Name: grab.c + * Description: grab.c + * + * Part of this code is from itouch-ctrl plugin. + * Authors of itouch-ctrl are listed below: + * + * Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov@gmail.com> + * + * Part of this code are from xmms-itouch plugin. + * Authors of xmms-itouch are listed below: + * + * Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi> + * Bryn Davies <curious@ihug.com.au> + * Jonathan A. Davis <davis@jdhouse.org> + * Jeremy Tan <nsx@nsx.homeip.net> + * + * audacious-hotkey is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * audacious-hotkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with audacious-hotkey; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> + +#include "grab.h" +#include "plugin.h" + + +static gint grabbed = 0; +static unsigned int numlock_mask = 0; +static unsigned int scrolllock_mask = 0; +static unsigned int capslock_mask = 0; + + +/* Taken from xbindkeys */ +static void get_offending_modifiers (Display * dpy) +{ + int i; + XModifierKeymap *modmap; + KeyCode nlock, slock; + + static int mask_table[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask + }; + + nlock = XKeysymToKeycode (dpy, XK_Num_Lock); + slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); + + /* + * Find out the masks for the NumLock and ScrollLock modifiers, + * so that we can bind the grabs for when they are enabled too. + */ + modmap = XGetModifierMapping (dpy); + + if (modmap != NULL && modmap->max_keypermod > 0) + { + for (i = 0; i < 8 * modmap->max_keypermod; i++) + { + if (modmap->modifiermap[i] == nlock && nlock != 0) + numlock_mask = mask_table[i / modmap->max_keypermod]; + else if (modmap->modifiermap[i] == slock && slock != 0) + scrolllock_mask = mask_table[i / modmap->max_keypermod]; + } + } + + capslock_mask = LockMask; + + if (modmap) + XFreeModifiermap (modmap); +} + + +static int x11_error_handler (Display *dpy, XErrorEvent *error) +{ + return 0; +} + +/* grab required keys */ +static void grab_key(HotkeyConfiguration hotkey, Display *xdisplay, Window x_root_window) +{ + unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); + + if (hotkey.key == 0) return; + + if (hotkey.type == TYPE_KEY) + { + XGrabKey (xdisplay, hotkey.key, modifier, x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (modifier == AnyModifier) + return; + + if (numlock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (capslock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (scrolllock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (numlock_mask && capslock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (numlock_mask && scrolllock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (capslock_mask && scrolllock_mask) + XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); + + if (numlock_mask && capslock_mask && scrolllock_mask) + XGrabKey (xdisplay, hotkey.key, + modifier | numlock_mask | capslock_mask | scrolllock_mask, + x_root_window, False, GrabModeAsync, + GrabModeAsync); + } + if (hotkey.type == TYPE_MOUSE) + { + XGrabButton (xdisplay, hotkey.key, modifier, x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (modifier == AnyModifier) + return; + + if (numlock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (capslock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (scrolllock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (numlock_mask && capslock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (numlock_mask && scrolllock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (capslock_mask && scrolllock_mask) + XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + + if (numlock_mask && capslock_mask && scrolllock_mask) + XGrabButton (xdisplay, hotkey.key, + modifier | numlock_mask | capslock_mask | scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); + } +} + +void grab_keys ( ) +{ + Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + Window x_root_window = GDK_WINDOW_XID(gdk_get_default_root_window()); + PluginConfig* plugin_cfg = get_config(); + XErrorHandler old_handler = 0; + + if (grabbed) return; + + + XSync(xdisplay, False); + old_handler = XSetErrorHandler (x11_error_handler); + + get_offending_modifiers(xdisplay); + + grab_key(plugin_cfg->mute, xdisplay, x_root_window); + grab_key(plugin_cfg->vol_up, xdisplay, x_root_window); + grab_key(plugin_cfg->vol_down, xdisplay, x_root_window); + grab_key(plugin_cfg->play, xdisplay, x_root_window); + grab_key(plugin_cfg->pause, xdisplay, x_root_window); + grab_key(plugin_cfg->stop, xdisplay, x_root_window); + grab_key(plugin_cfg->prev_track, xdisplay, x_root_window); + grab_key(plugin_cfg->next_track, xdisplay, x_root_window); + grab_key(plugin_cfg->jump_to_file, xdisplay, x_root_window); + grab_key(plugin_cfg->forward, xdisplay, x_root_window); + grab_key(plugin_cfg->backward, xdisplay, x_root_window); + grab_key(plugin_cfg->toggle_win, xdisplay, x_root_window); + grab_key(plugin_cfg->show_aosd, xdisplay, x_root_window); + + XSync(xdisplay, False); + XSetErrorHandler (old_handler); + + grabbed = 1; +} + + + +/* grab required keys */ +static void ungrab_key(HotkeyConfiguration hotkey, Display* xdisplay, Window x_root_window) +{ + unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); + + if (hotkey.key == 0) return; + + if (hotkey.type == TYPE_KEY) + { + XUngrabKey (xdisplay, hotkey.key, modifier, x_root_window); + + if (modifier == AnyModifier) + return; + + if (numlock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); + + if (capslock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); + + if (scrolllock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); + + if (numlock_mask && capslock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); + + if (numlock_mask && scrolllock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); + + if (capslock_mask && scrolllock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); + + if (numlock_mask && capslock_mask && scrolllock_mask) + XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); + } + if (hotkey.type == TYPE_MOUSE) + { + XUngrabButton (xdisplay, hotkey.key, modifier, x_root_window); + + if (modifier == AnyModifier) + return; + + if (numlock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); + + if (capslock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); + + if (scrolllock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); + + if (numlock_mask && capslock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); + + if (numlock_mask && scrolllock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); + + if (capslock_mask && scrolllock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); + + if (numlock_mask && capslock_mask && scrolllock_mask) + XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); + } +} + +void ungrab_keys ( ) +{ + XErrorHandler old_handler = 0; + Display* xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + Window x_root_window = GDK_WINDOW_XID(gdk_get_default_root_window()); + PluginConfig* plugin_cfg = get_config(); + + if (!grabbed) return; + if (!xdisplay) return; + + XSync(xdisplay, False); + old_handler = XSetErrorHandler (x11_error_handler); + + get_offending_modifiers(xdisplay); + + ungrab_key(plugin_cfg->mute, xdisplay, x_root_window); + ungrab_key(plugin_cfg->vol_up, xdisplay, x_root_window); + ungrab_key(plugin_cfg->vol_down, xdisplay, x_root_window); + ungrab_key(plugin_cfg->play, xdisplay, x_root_window); + ungrab_key(plugin_cfg->pause, xdisplay, x_root_window); + ungrab_key(plugin_cfg->stop, xdisplay, x_root_window); + ungrab_key(plugin_cfg->prev_track, xdisplay, x_root_window); + ungrab_key(plugin_cfg->next_track, xdisplay, x_root_window); + ungrab_key(plugin_cfg->jump_to_file, xdisplay, x_root_window); + ungrab_key(plugin_cfg->forward, xdisplay, x_root_window); + ungrab_key(plugin_cfg->backward, xdisplay, x_root_window); + ungrab_key(plugin_cfg->toggle_win, xdisplay, x_root_window); + ungrab_key(plugin_cfg->show_aosd, xdisplay, x_root_window); + + XSync(xdisplay, False); + XSetErrorHandler (old_handler); + + grabbed = 0; +} + + +static GdkFilterReturn +gdk_filter(GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + switch (((XEvent*)xevent)->type) + { + case KeyPress: + { + XKeyEvent *keyevent = (XKeyEvent*)xevent; + if (handle_keyevent(keyevent->keycode, keyevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask), TYPE_KEY)) + return GDK_FILTER_REMOVE; + break; + } + case ButtonPress: + { + XButtonEvent *buttonevent = (XButtonEvent*)xevent; + if (handle_keyevent(buttonevent->button, buttonevent->state, TYPE_MOUSE)) + return GDK_FILTER_REMOVE; + break; + } + default: + return -1; + } + + return GDK_FILTER_CONTINUE; +} + +gboolean setup_filter() +{ + gdk_window_add_filter(gdk_get_default_root_window(), + gdk_filter, + NULL); + + return TRUE; +} + +void release_filter() +{ + gdk_window_remove_filter(gdk_get_default_root_window(), + gdk_filter, + NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotkey/grab.h Sun Jan 20 14:52:44 2008 +0100 @@ -0,0 +1,11 @@ +#ifndef _GRAB_H_INCLUDED_ +#define _GRAB_H_INCLUDED_ + +#include <glib.h> + +void grab_keys (); +void ungrab_keys (); +gboolean setup_filter(); +void release_filter(); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotkey/gui.c Sun Jan 20 14:52:44 2008 +0100 @@ -0,0 +1,566 @@ +/* + * This file is part of audacious-hotkey plugin for audacious + * + * Copyright (c) 2007 - 2008 Sascha Hlusiak <contact@saschahlusiak.de> + * Name: gui.c + * Description: gui.c + * + * Part of this code is from itouch-ctrl plugin. + * Authors of itouch-ctrl are listed below: + * + * Copyright (c) 2006 - 2007 Vladimir Paskov <vlado.paskov@gmail.com> + * + * Part of this code are from xmms-itouch plugin. + * Authors of xmms-itouch are listed below: + * + * Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi> + * Bryn Davies <curious@ihug.com.au> + * Jonathan A. Davis <davis@jdhouse.org> + * Jeremy Tan <nsx@nsx.homeip.net> + * + * audacious-hotkey is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * audacious-hotkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with audacious-hotkey; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> +#include <gdk/gdkkeysyms.h> + +#include <audacious/i18n.h> +#include <audacious/util.h> + +#include "plugin.h" +#include "gui.h" +#include "grab.h" + + +typedef struct { + GtkWidget *keytext; + HotkeyConfiguration hotkey; +} KeyControls; + +typedef struct { + KeyControls play; + KeyControls stop; + KeyControls pause; + KeyControls prev_track; + KeyControls next_track; + KeyControls vol_up; + KeyControls vol_down; + KeyControls mute; + KeyControls jump_to_file; + KeyControls forward; + KeyControls backward; + KeyControls toggle_win; + KeyControls show_aosd; +} ConfigurationControls; + + + +static void clear_keyboard (GtkWidget *widget, gpointer data); +static void cancel_callback (GtkWidget *widget, gpointer data); +static void destroy_callback (GtkWidget *widget, gpointer data); +static void ok_callback (GtkWidget *widget, gpointer data); + + +static void set_keytext (GtkWidget *entry, gint key, gint mask, gint type) +{ + gchar *text = NULL; + + if (key == 0 && mask == 0) + { + text = g_strdup(_("(none)")); + } else { + static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" }; + static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; + gchar *strings[9]; + gchar *keytext = NULL; + int i, j; + if (type == TYPE_KEY) + { + KeySym keysym; + keysym = XKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0); + if (keysym == 0 || keysym == NoSymbol) + { + keytext = g_strdup_printf("#%d", key); + } else { + keytext = g_strdup(XKeysymToString(keysym)); + } + } + if (type == TYPE_MOUSE) + { + keytext = g_strdup_printf("Button%d", key); + } + + for (i = 0, j=0; j<7; j++) + { + if (mask & modifiers[j]) + strings[i++] = modifier_string[j]; + } + if (key != 0) strings[i++] = keytext; + strings[i] = NULL; + + text = g_strjoinv(" + ", strings); + g_free(keytext); + } + + gtk_entry_set_text(GTK_ENTRY(entry), text); + gtk_editable_set_position(GTK_EDITABLE(entry), -1); + if (text) g_free(text); +} + +static gboolean +on_entry_key_press_event(GtkWidget * widget, + GdkEventKey * event, + gpointer user_data) +{ + KeyControls *controls = (KeyControls*) user_data; + int is_mod; + int mod; + + if (event->keyval == GDK_Tab) return FALSE; + + mod = 0; + is_mod = 0; + + if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) + mod |= ControlMask; + + if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) + mod |= Mod1Mask; + + if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) + mod |= ShiftMask; + + if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) + mod |= Mod5Mask; + + if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) + mod |= Mod4Mask; + + if (!is_mod) { + controls->hotkey.key = event->hardware_keycode; + controls->hotkey.mask = mod; + controls->hotkey.type = TYPE_KEY; + } else controls->hotkey.key = 0; + + set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); + return TRUE; +} + +static gboolean +on_entry_key_release_event(GtkWidget * widget, + GdkEventKey * event, + gpointer user_data) +{ + KeyControls *controls = (KeyControls*) user_data; + if (controls->hotkey.key == 0) { + controls->hotkey.mask = 0; + return TRUE; + } + set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + return TRUE; +} + +static gboolean +on_entry_button_press_event(GtkWidget * widget, + GdkEventButton * event, + gpointer user_data) +{ + KeyControls *controls = (KeyControls*) user_data; + int mod; + + if (!gtk_widget_is_focus(widget)) return FALSE; + + mod = 0; + if (event->state & GDK_CONTROL_MASK) + mod |= ControlMask; + + if (event->state & GDK_MOD1_MASK) + mod |= Mod1Mask; + + if (event->state & GDK_SHIFT_MASK) + mod |= ShiftMask; + + if (event->state & GDK_MOD5_MASK) + mod |= Mod5Mask; + + if (event->state & GDK_MOD4_MASK) + mod |= Mod4Mask; + + if ((event->button <= 3) && (mod == 0)) + { + GtkWidget* dialog; + GtkResponseType response; + dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)), + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_YES_NO, + _("It is not recommended to bind the primary mouse buttons without modificators.\n\n" + "Do you want to continue?")); + gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy (dialog); + if (response != GTK_RESPONSE_YES) return TRUE; + } + + controls->hotkey.key = event->button; + controls->hotkey.mask = mod; + controls->hotkey.type = TYPE_MOUSE; + set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + return TRUE; +} + +static gboolean +on_entry_scroll_event(GtkWidget * widget, + GdkEventScroll * event, + gpointer user_data) +{ + KeyControls *controls = (KeyControls*) user_data; + int mod; + + if (!gtk_widget_is_focus(widget)) return FALSE; + + mod = 0; + if (event->state & GDK_CONTROL_MASK) + mod |= ControlMask; + + if (event->state & GDK_MOD1_MASK) + mod |= Mod1Mask; + + if (event->state & GDK_SHIFT_MASK) + mod |= ShiftMask; + + if (event->state & GDK_MOD5_MASK) + mod |= Mod5Mask; + + if (event->state & GDK_MOD4_MASK) + mod |= Mod4Mask; + + if (event->direction == GDK_SCROLL_UP) + controls->hotkey.key = 4; + else if (event->direction == GDK_SCROLL_DOWN) + controls->hotkey.key = 5; + else if (event->direction == GDK_SCROLL_LEFT) + controls->hotkey.key = 6; + else if (event->direction == GDK_SCROLL_RIGHT) + controls->hotkey.key = 7; + else return FALSE; + + controls->hotkey.mask = mod; + controls->hotkey.type = TYPE_MOUSE; + set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + return TRUE; +} + +static void add_event_controls(GtkWidget *table, + KeyControls *controls, + int row, + char* descr, + char* tooltip, + HotkeyConfiguration hotkey) +{ + GtkWidget *label; + GtkWidget *button; + + controls->hotkey.key = hotkey.key; + controls->hotkey.mask = hotkey.mask; + controls->hotkey.type = hotkey.type; + if (controls->hotkey.key == 0) + controls->hotkey.mask = 0; + + label = gtk_label_new (_(descr)); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, + (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_misc_set_padding (GTK_MISC (label), 3, 3); + + controls->keytext = gtk_entry_new (); + gtk_table_attach (GTK_TABLE (table), controls->keytext, 1, 2, row, row+1, + (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0); + gtk_entry_set_editable (GTK_ENTRY (controls->keytext), FALSE); + + set_keytext(controls->keytext, hotkey.key, hotkey.mask, hotkey.type); + g_signal_connect((gpointer)controls->keytext, "key_press_event", + G_CALLBACK(on_entry_key_press_event), controls); + g_signal_connect((gpointer)controls->keytext, "key_release_event", + G_CALLBACK(on_entry_key_release_event), controls); + g_signal_connect((gpointer)controls->keytext, "button_press_event", + G_CALLBACK(on_entry_button_press_event), controls); + g_signal_connect((gpointer)controls->keytext, "scroll_event", + G_CALLBACK(on_entry_scroll_event), controls); + + button = gtk_button_new_with_label (_("None")); + gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (clear_keyboard), controls); + + if (tooltip != NULL) { + GtkTooltips *tip = gtk_tooltips_new(); + gtk_tooltips_set_tip(tip, controls->keytext, tooltip, NULL); + gtk_tooltips_set_tip(tip, button, tooltip, NULL); + gtk_tooltips_set_tip(tip, label, tooltip, NULL); + } +} + +void show_configure () +{ + ConfigurationControls *controls; + GtkWidget *window; + GtkWidget *main_vbox, *vbox; + GtkWidget *hbox; + GtkWidget *alignment; + GtkWidget *frame; + GtkWidget *label; + GtkWidget *image; + GtkWidget *table; + GtkWidget *button_box, *button; + PluginConfig* plugin_cfg; + + load_config ( ); + + plugin_cfg = get_config(); + + ungrab_keys(); + + controls = (ConfigurationControls*)g_malloc(sizeof(ConfigurationControls)); + if (!controls) + { + printf ("Faild to allocate memory for ConfigurationControls structure!\n" + "Aborting!"); + return; + } + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), _("Global Hotkey Plugin Configuration")); + gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ALWAYS); + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_resizable (GTK_WINDOW (window), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (window), 5); + + main_vbox = gtk_vbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (window), main_vbox); + + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_box_pack_start (GTK_BOX (main_vbox), alignment, FALSE, TRUE, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); + hbox = gtk_hbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (alignment), hbox); + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); + label = gtk_label_new (_("Press a key combination inside a text field.")); + gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("<b>Playback:</b>")); + frame = gtk_frame_new (NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_container_add (GTK_CONTAINER (frame), alignment); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); + vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (alignment), vbox); + label = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_label_set_markup (GTK_LABEL (label), + _("<i>Configure keys which controls Audacious playback.</i>")); + table = gtk_table_new (4, 3, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_table_set_row_spacings (GTK_TABLE (table), 2); + + /* prev track */ + add_event_controls(table, &controls->prev_track, 0, _("Previous Track:"), NULL, + plugin_cfg->prev_track); + + add_event_controls(table, &controls->play, 1, _("Play:"), NULL, + plugin_cfg->play); + + add_event_controls(table, &controls->pause, 2, _("Pause/Resume:"), NULL, + plugin_cfg->pause); + + add_event_controls(table, &controls->stop, 3, _("Stop:"), NULL, + plugin_cfg->stop); + + add_event_controls(table, &controls->next_track, 4, _("Next Track:"), NULL, + plugin_cfg->next_track); + + add_event_controls(table, &controls->forward, 5, _("Forward 5 sec.:"), NULL, + plugin_cfg->forward); + + add_event_controls(table, &controls->backward, 6, _("Rewind 5 sec.:"), NULL, + plugin_cfg->backward); + + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("<b>Volume Control:</b>")); + frame = gtk_frame_new (NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_container_add (GTK_CONTAINER (frame), alignment); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); + vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (alignment), vbox); + label = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_label_set_markup (GTK_LABEL (label), + _("<i>Configure keys which controls music volume.</i>")); + table = gtk_table_new (3, 3, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_table_set_row_spacings (GTK_TABLE (table), 2); + + add_event_controls(table, &controls->mute, 0, _("Mute:"),NULL, + plugin_cfg->mute); + + add_event_controls(table, &controls->vol_up, 1, _("Volume Up:"), NULL, + plugin_cfg->vol_up); + + add_event_controls(table, &controls->vol_down, 2, _("Volume Down:"), NULL, + plugin_cfg->vol_down); + + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), _("<b>Player:</b>")); + frame = gtk_frame_new (NULL); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_container_add (GTK_CONTAINER (frame), alignment); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); + vbox = gtk_vbox_new (FALSE, 2); + gtk_container_add (GTK_CONTAINER (alignment), vbox); + label = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_label_set_markup (GTK_LABEL (label), + _("<i>Configure keys which control the player.</i>")); + table = gtk_table_new (3, 3, FALSE); + gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); + gtk_table_set_col_spacings (GTK_TABLE (table), 2); + gtk_table_set_row_spacings (GTK_TABLE (table), 2); + + add_event_controls(table, &controls->jump_to_file, 0, _("Jump to File:"), NULL, + plugin_cfg->jump_to_file); + + add_event_controls(table, &controls->toggle_win, 1, _("Toggle Player Windows:"), NULL, + plugin_cfg->toggle_win); + + add_event_controls(table, &controls->show_aosd, 2, _("Show On-Screen-Display:"), + _("For this, the Audacious OSD plugin must be activated."), + plugin_cfg->show_aosd); + + button_box = gtk_hbutton_box_new ( ); + gtk_box_pack_start (GTK_BOX (main_vbox), button_box, FALSE, TRUE, 6); + gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (button_box), 4); + + button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); + gtk_container_add (GTK_CONTAINER (button_box), button); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (cancel_callback), controls); + + button = gtk_button_new_from_stock (GTK_STOCK_OK); + gtk_container_add (GTK_CONTAINER (button_box), button); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (ok_callback), controls); + + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (destroy_callback), controls); + + gtk_widget_show_all (GTK_WIDGET (window)); +} + +static void clear_keyboard (GtkWidget *widget, gpointer data) +{ + KeyControls *spins = (KeyControls*)data; + spins->hotkey.key = 0; + spins->hotkey.mask = 0; + spins->hotkey.type = TYPE_KEY; + set_keytext(spins->keytext, 0, 0, TYPE_KEY); +} + +void destroy_callback (GtkWidget *widget, gpointer data) +{ + if (is_loaded()) + { + grab_keys (); + } + if (data) g_free(data); +} + +void cancel_callback (GtkWidget *widget, gpointer data) +{ + gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); +} + +void ok_callback (GtkWidget *widget, gpointer data) +{ + ConfigurationControls *controls= (ConfigurationControls*)data; + PluginConfig* plugin_cfg = get_config(); + + plugin_cfg->play = controls->play.hotkey; + plugin_cfg->pause = controls->pause.hotkey; + plugin_cfg->stop= controls->stop.hotkey; + plugin_cfg->prev_track= controls->prev_track.hotkey; + plugin_cfg->next_track = controls->next_track.hotkey; + plugin_cfg->forward = controls->forward.hotkey; + plugin_cfg->backward = controls->backward.hotkey; + plugin_cfg->vol_up= controls->vol_up.hotkey; + plugin_cfg->vol_down = controls->vol_down.hotkey; + plugin_cfg->mute = controls->mute.hotkey; + plugin_cfg->jump_to_file= controls->jump_to_file.hotkey; + plugin_cfg->toggle_win = controls->toggle_win.hotkey; + plugin_cfg->show_aosd = controls->show_aosd.hotkey; + + save_config ( ); + + gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); +} + + + +void show_about (void) +{ + static GtkWidget *dialog; + + dialog = audacious_info_dialog (_("About Global Hotkey Plugin"), + _("Global Hotkey Plugin\n" + "Control the player with global key combinations or multimedia keys.\n\n" + "Copyright (C) 2007-2008 Sascha Hlusiak <contact@saschahlusiak.de>\n\n" + "Contributers include:\n" + "Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov@gmail.com>\n" + "Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi>\n" + " Bryn Davies <curious@ihug.com.au>\n" + " Jonathan A. Davis <davis@jdhouse.org>\n" + " Jeremy Tan <nsx@nsx.homeip.net>\n\n" + ), + _("OK"), TRUE, NULL, NULL); + + gtk_signal_connect(GTK_OBJECT(dialog), "destroy", + GTK_SIGNAL_FUNC(gtk_widget_destroyed), &dialog); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotkey/gui.h Sun Jan 20 14:52:44 2008 +0100 @@ -0,0 +1,7 @@ +#ifndef _GUI_H_INCLUDED_ +#define _GUI_H_INCLUDED_ + +void show_configure (void); +void show_about (void); + +#endif
--- a/src/hotkey/plugin.c Tue Jan 15 12:35:54 2008 +0200 +++ b/src/hotkey/plugin.c Sun Jan 20 14:52:44 2008 +0100 @@ -1,4 +1,3 @@ -/* -*- Mode: C; indent-tabs: t; c-basic-offset: 9; tab-width: 9 -*- */ /* * This file is part of audacious-hotkey plugin for audacious * @@ -37,112 +36,37 @@ #include <config.h> #include <stdio.h> -#include <stdlib.h> -#include <X11/Xlib.h> -#include <X11/keysym.h> #include <X11/XF86keysym.h> -#include <gtk/gtk.h> #include <gdk/gdkx.h> -#include <gdk/gdkkeysyms.h> #include <audacious/plugin.h> #include <audacious/auddrct.h> #include <audacious/configdb.h> #include <audacious/i18n.h> -/* for audacious_info_dialog () */ -#include <audacious/util.h> +#include "plugin.h" +#include "gui.h" +#include "grab.h" /* func defs */ -void x_display_init (void); -static void get_offending_modifiers (Display * dpy); static void init (void); -static void grab_keys (); -static void ungrab_keys (); -static gboolean handle_keyevent(int keycode, int state, int type); -static gboolean setup_filter(); -static void release_filter(); - -static void load_config (void); -static void save_config (void); -static void configure (void); -static void clear_keyboard (GtkWidget *widget, gpointer data); - -void cancel_callback (GtkWidget *widget, gpointer data); -void ok_callback (GtkWidget *widget, gpointer data); -static void about (void); static void cleanup (void); -#define TYPE_KEY 0 -#define TYPE_MOUSE 1 - -typedef struct { - gint key, mask; - gint type; -} HotkeyConfiguration; - -typedef struct { - gint vol_increment; - gint vol_decrement; - - /* keyboard */ - HotkeyConfiguration mute; - HotkeyConfiguration vol_down; - HotkeyConfiguration vol_up; - HotkeyConfiguration play; - HotkeyConfiguration stop; - HotkeyConfiguration pause; - HotkeyConfiguration prev_track; - HotkeyConfiguration next_track; - HotkeyConfiguration jump_to_file; - HotkeyConfiguration toggle_win; - HotkeyConfiguration forward; - HotkeyConfiguration backward; - HotkeyConfiguration show_aosd; -} PluginConfig; - -PluginConfig plugin_cfg; - -static Display *xdisplay = NULL; -static Window x_root_window = 0; -static gint grabbed = 0; +/* global vars */ +static PluginConfig plugin_cfg; static gboolean loaded = FALSE; -static unsigned int numlock_mask = 0; -static unsigned int scrolllock_mask = 0; -static unsigned int capslock_mask = 0; -typedef struct { - GtkWidget *keytext; - HotkeyConfiguration hotkey; -} KeyControls; - -typedef struct { - KeyControls play; - KeyControls stop; - KeyControls pause; - KeyControls prev_track; - KeyControls next_track; - KeyControls vol_up; - KeyControls vol_down; - KeyControls mute; - KeyControls jump_to_file; - KeyControls forward; - KeyControls backward; - KeyControls toggle_win; - KeyControls show_aosd; -} ConfigurationControls; - static GeneralPlugin audacioushotkey = { .description = "Global Hotkey", .init = init, - .about = about, - .configure = configure, + .about = show_about, + .configure = show_configure, .cleanup = cleanup }; @@ -151,67 +75,26 @@ +PluginConfig* get_config(void) +{ + return &plugin_cfg; +} + + /* * plugin activated */ static void init (void) { - x_display_init ( ); setup_filter(); load_config ( ); - grab_keys (); + grab_keys ( ); loaded = TRUE; } -/* check X display */ -void x_display_init (void) -{ - if (xdisplay != NULL) return; - xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - x_root_window = GDK_WINDOW_XID(gdk_get_default_root_window()); - get_offending_modifiers(xdisplay); -} - -/* Taken from xbindkeys */ -static void get_offending_modifiers (Display * dpy) -{ - int i; - XModifierKeymap *modmap; - KeyCode nlock, slock; - static int mask_table[8] = { - ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask - }; - - nlock = XKeysymToKeycode (dpy, XK_Num_Lock); - slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); - - /* - * Find out the masks for the NumLock and ScrollLock modifiers, - * so that we can bind the grabs for when they are enabled too. - */ - modmap = XGetModifierMapping (dpy); - - if (modmap != NULL && modmap->max_keypermod > 0) - { - for (i = 0; i < 8 * modmap->max_keypermod; i++) - { - if (modmap->modifiermap[i] == nlock && nlock != 0) - numlock_mask = mask_table[i / modmap->max_keypermod]; - else if (modmap->modifiermap[i] == slock && slock != 0) - scrolllock_mask = mask_table[i / modmap->max_keypermod]; - } - } - - capslock_mask = LockMask; - - if (modmap) - XFreeModifiermap (modmap); -} - /* handle keys */ -static gboolean handle_keyevent (int keycode, int state, int type) +gboolean handle_keyevent (int keycode, int state, int type) { gint current_volume, old_volume; static gint volume_static = 0; @@ -232,8 +115,6 @@ mute = TRUE; } - state &= ~(scrolllock_mask | numlock_mask | capslock_mask); - /* mute the playback */ if ((keycode == plugin_cfg.mute.key) && (state == plugin_cfg.mute.mask) && (type == plugin_cfg.mute.type)) { @@ -390,64 +271,17 @@ return FALSE; } -static GdkFilterReturn -gdk_filter(GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - switch (((XEvent*)xevent)->type) - { - case KeyPress: - { - XKeyEvent *keyevent = (XKeyEvent*)xevent; - if (handle_keyevent(keyevent->keycode, keyevent->state, TYPE_KEY)) - return GDK_FILTER_REMOVE; - break; - } - case ButtonPress: - { - XButtonEvent *buttonevent = (XButtonEvent*)xevent; - if (handle_keyevent(buttonevent->button, buttonevent->state, TYPE_MOUSE)) - return GDK_FILTER_REMOVE; - break; - } - default: - return -1; - } - - return GDK_FILTER_CONTINUE; -} - -static gboolean -setup_filter() -{ - gdk_window_add_filter(gdk_get_default_root_window(), - gdk_filter, - NULL); - - return TRUE; -} - -static void release_filter() -{ - gdk_window_remove_filter(gdk_get_default_root_window(), - gdk_filter, - NULL); -} - /* load plugin configuration */ -static void load_config (void) +void load_config (void) { ConfigDb *cfdb; - if (xdisplay == NULL) x_display_init(); - /* default volume level */ plugin_cfg.vol_increment = 4; plugin_cfg.vol_decrement = 4; #define load_key(hotkey,default) \ - plugin_cfg.hotkey.key = (default)?(XKeysymToKeycode(xdisplay, (default))):0; \ + plugin_cfg.hotkey.key = (default)?(XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), (default))):0; \ plugin_cfg.hotkey.mask = 0; \ plugin_cfg.hotkey.type = TYPE_KEY; \ aud_cfg_db_get_int (cfdb, "globalHotkey", #hotkey, &plugin_cfg.hotkey.key); \ @@ -476,7 +310,7 @@ } /* save plugin configuration */ -static void save_config (void) +void save_config (void) { ConfigDb *cfdb; @@ -505,633 +339,6 @@ aud_cfg_db_close (cfdb); } -static int x11_error_handler (Display *dpy, XErrorEvent *error) -{ - return 0; -} - -/* grab required keys */ -static void grab_key(HotkeyConfiguration hotkey) -{ - unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - - if (hotkey.key == 0) return; - - if (hotkey.type == TYPE_KEY) - { - XGrabKey (xdisplay, hotkey.key, modifier, x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (modifier == AnyModifier) - return; - - if (numlock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (capslock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (scrolllock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (numlock_mask && capslock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (numlock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (capslock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); - - if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey.key, - modifier | numlock_mask | capslock_mask | scrolllock_mask, - x_root_window, False, GrabModeAsync, - GrabModeAsync); - } - if (hotkey.type == TYPE_MOUSE) - { - XGrabButton (xdisplay, hotkey.key, modifier, x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (modifier == AnyModifier) - return; - - if (numlock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (capslock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (scrolllock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (numlock_mask && capslock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (numlock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (capslock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); - - if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey.key, - modifier | numlock_mask | capslock_mask | scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); - } -} - -static void grab_keys () -{ - if (grabbed) return; - if (xdisplay == NULL) x_display_init(); - - XErrorHandler old_handler = 0; - - XSync(xdisplay, False); - old_handler = XSetErrorHandler (x11_error_handler); - - grab_key(plugin_cfg.mute); - grab_key(plugin_cfg.vol_up); - grab_key(plugin_cfg.vol_down); - grab_key(plugin_cfg.play); - grab_key(plugin_cfg.pause); - grab_key(plugin_cfg.stop); - grab_key(plugin_cfg.prev_track); - grab_key(plugin_cfg.next_track); - grab_key(plugin_cfg.jump_to_file); - grab_key(plugin_cfg.forward); - grab_key(plugin_cfg.backward); - grab_key(plugin_cfg.toggle_win); - grab_key(plugin_cfg.show_aosd); - - XSync(xdisplay, False); - XSetErrorHandler (old_handler); - - grabbed = 1; -} -/* - * plugin init end - */ - -static void set_keytext (GtkWidget *entry, gint key, gint mask, gint type) -{ - gchar *text = NULL; - - if (key == 0 && mask == 0) - { - text = g_strdup(_("(none)")); - } else { - static char *modifier_string[] = { "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5" }; - static unsigned int modifiers[] = { ControlMask, ShiftMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; - gchar *strings[9]; - gchar *keytext = NULL; - int i, j; - if (type == TYPE_KEY) - { - KeySym keysym; - keysym = XKeycodeToKeysym(xdisplay, key, 0); - if (keysym == 0 || keysym == NoSymbol) - { - keytext = g_strdup_printf("#%d", key); - } else { - keytext = g_strdup(XKeysymToString(keysym)); - } - } - if (type == TYPE_MOUSE) - { - keytext = g_strdup_printf("Button%d", key); - } - - for (i = 0, j=0; j<7; j++) - { - if (mask & modifiers[j]) - strings[i++] = modifier_string[j]; - } - if (key != 0) strings[i++] = keytext; - strings[i] = NULL; - - text = g_strjoinv(" + ", strings); - g_free(keytext); - } - - gtk_entry_set_text(GTK_ENTRY(entry), text); - gtk_editable_set_position(GTK_EDITABLE(entry), -1); - if (text) g_free(text); -} - -static gboolean -on_entry_key_press_event(GtkWidget * widget, - GdkEventKey * event, - gpointer user_data) -{ - KeyControls *controls = (KeyControls*) user_data; - int is_mod; - int mod; - - if (event->keyval == GDK_Tab) return FALSE; - - mod = 0; - is_mod = 0; - - if ((event->state & GDK_CONTROL_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) - mod |= ControlMask; - - if ((event->state & GDK_MOD1_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) - mod |= Mod1Mask; - - if ((event->state & GDK_SHIFT_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) - mod |= ShiftMask; - - if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) - mod |= Mod5Mask; - - if ((event->state & GDK_MOD4_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) - mod |= Mod4Mask; - - if (!is_mod) { - controls->hotkey.key = event->hardware_keycode; - controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_KEY; - } else controls->hotkey.key = 0; - - set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); - return TRUE; -} - -static gboolean -on_entry_key_release_event(GtkWidget * widget, - GdkEventKey * event, - gpointer user_data) -{ - KeyControls *controls = (KeyControls*) user_data; - if (controls->hotkey.key == 0) { - controls->hotkey.mask = 0; - return TRUE; - } - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); - return TRUE; -} - -static gboolean -on_entry_button_press_event(GtkWidget * widget, - GdkEventButton * event, - gpointer user_data) -{ - KeyControls *controls = (KeyControls*) user_data; - int mod; - - if (!gtk_widget_is_focus(widget)) return FALSE; - - mod = 0; - if (event->state & GDK_CONTROL_MASK) - mod |= ControlMask; - - if (event->state & GDK_MOD1_MASK) - mod |= Mod1Mask; - - if (event->state & GDK_SHIFT_MASK) - mod |= ShiftMask; - - if (event->state & GDK_MOD5_MASK) - mod |= Mod5Mask; - - if (event->state & GDK_MOD4_MASK) - mod |= Mod4Mask; - - if ((event->button <= 3) && (mod == 0)) - { - GtkWidget* dialog; - GtkResponseType response; - dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_YES_NO, - _("It is not recommended to bind the primary mouse buttons without modificators.\n\n" - "Do you want to continue?")); - gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); - response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy (dialog); - if (response != GTK_RESPONSE_YES) return TRUE; - } - - controls->hotkey.key = event->button; - controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); - return TRUE; -} - -static gboolean -on_entry_scroll_event(GtkWidget * widget, - GdkEventScroll * event, - gpointer user_data) -{ - KeyControls *controls = (KeyControls*) user_data; - int mod; - - if (!gtk_widget_is_focus(widget)) return FALSE; - - mod = 0; - if (event->state & GDK_CONTROL_MASK) - mod |= ControlMask; - - if (event->state & GDK_MOD1_MASK) - mod |= Mod1Mask; - - if (event->state & GDK_SHIFT_MASK) - mod |= ShiftMask; - - if (event->state & GDK_MOD5_MASK) - mod |= Mod5Mask; - - if (event->state & GDK_MOD4_MASK) - mod |= Mod4Mask; - - if (event->direction == GDK_SCROLL_UP) - controls->hotkey.key = 4; - else if (event->direction == GDK_SCROLL_DOWN) - controls->hotkey.key = 5; - else if (event->direction == GDK_SCROLL_LEFT) - controls->hotkey.key = 6; - else if (event->direction == GDK_SCROLL_RIGHT) - controls->hotkey.key = 7; - else return FALSE; - - controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); - return TRUE; -} - -static void add_event_controls(GtkWidget *table, - KeyControls *controls, - int row, - char* descr, - char* tooltip, - HotkeyConfiguration hotkey) -{ - GtkWidget *label; - GtkWidget *button; - - controls->hotkey.key = hotkey.key; - controls->hotkey.mask = hotkey.mask; - controls->hotkey.type = hotkey.type; - if (controls->hotkey.key == 0) - controls->hotkey.mask = 0; - - label = gtk_label_new (_(descr)); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, - (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - gtk_misc_set_padding (GTK_MISC (label), 3, 3); - - controls->keytext = gtk_entry_new (); - gtk_table_attach (GTK_TABLE (table), controls->keytext, 1, 2, row, row+1, - (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0); - gtk_entry_set_editable (GTK_ENTRY (controls->keytext), FALSE); - - set_keytext(controls->keytext, hotkey.key, hotkey.mask, hotkey.type); - g_signal_connect((gpointer)controls->keytext, "key_press_event", - G_CALLBACK(on_entry_key_press_event), controls); - g_signal_connect((gpointer)controls->keytext, "key_release_event", - G_CALLBACK(on_entry_key_release_event), controls); - g_signal_connect((gpointer)controls->keytext, "button_press_event", - G_CALLBACK(on_entry_button_press_event), controls); - g_signal_connect((gpointer)controls->keytext, "scroll_event", - G_CALLBACK(on_entry_scroll_event), controls); - - button = gtk_button_new_with_label (_("None")); - gtk_table_attach (GTK_TABLE (table), button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0); - g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (clear_keyboard), controls); - - if (tooltip != NULL) { - GtkTooltips *tip = gtk_tooltips_new(); - gtk_tooltips_set_tip(tip, controls->keytext, tooltip, NULL); - gtk_tooltips_set_tip(tip, button, tooltip, NULL); - gtk_tooltips_set_tip(tip, label, tooltip, NULL); - } -} - -/* configuration window */ -static void configure (void) -{ - ConfigurationControls *controls; - GtkWidget *window; - GtkWidget *main_vbox, *vbox; - GtkWidget *hbox; - GtkWidget *alignment; - GtkWidget *frame; - GtkWidget *label; - GtkWidget *image; - GtkWidget *table; - GtkWidget *button_box, *button; - - if (!xdisplay) x_display_init(); - - load_config ( ); - - ungrab_keys(); - - controls = (ConfigurationControls*)g_malloc(sizeof(ConfigurationControls)); - if (!controls) - { - printf ("Faild to allocate memory for ConfigurationControls structure!\n" - "Aborting!"); - return; - } - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), _("Global Hotkey Plugin Configuration")); - gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER_ALWAYS); - gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_resizable (GTK_WINDOW (window), FALSE); - gtk_container_set_border_width (GTK_CONTAINER (window), 5); - - main_vbox = gtk_vbox_new (FALSE, 4); - gtk_container_add (GTK_CONTAINER (window), main_vbox); - - alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_box_pack_start (GTK_BOX (main_vbox), alignment, FALSE, TRUE, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); - hbox = gtk_hbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (alignment), hbox); - image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); - label = gtk_label_new (_("Press a key combination inside a text field.")); - gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), _("<b>Playback:</b>")); - frame = gtk_frame_new (NULL); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_container_add (GTK_CONTAINER (frame), alignment); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (alignment), vbox); - label = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), - _("<i>Configure keys which controls Audacious playback.</i>")); - table = gtk_table_new (4, 3, FALSE); - gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); - gtk_table_set_col_spacings (GTK_TABLE (table), 2); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - - /* prev track */ - add_event_controls(table, &controls->prev_track, 0, _("Previous Track:"), NULL, - plugin_cfg.prev_track); - - add_event_controls(table, &controls->play, 1, _("Play:"), NULL, - plugin_cfg.play); - - add_event_controls(table, &controls->pause, 2, _("Pause/Resume:"), NULL, - plugin_cfg.pause); - - add_event_controls(table, &controls->stop, 3, _("Stop:"), NULL, - plugin_cfg.stop); - - add_event_controls(table, &controls->next_track, 4, _("Next Track:"), NULL, - plugin_cfg.next_track); - - add_event_controls(table, &controls->forward, 5, _("Forward 5 sec.:"), NULL, - plugin_cfg.forward); - - add_event_controls(table, &controls->backward, 6, _("Rewind 5 sec.:"), NULL, - plugin_cfg.backward); - - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), _("<b>Volume Control:</b>")); - frame = gtk_frame_new (NULL); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_container_add (GTK_CONTAINER (frame), alignment); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (alignment), vbox); - label = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), - _("<i>Configure keys which controls music volume.</i>")); - table = gtk_table_new (3, 3, FALSE); - gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); - gtk_table_set_col_spacings (GTK_TABLE (table), 2); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - - add_event_controls(table, &controls->mute, 0, _("Mute:"),NULL, - plugin_cfg.mute); - - add_event_controls(table, &controls->vol_up, 1, _("Volume Up:"), NULL, - plugin_cfg.vol_up); - - add_event_controls(table, &controls->vol_down, 2, _("Volume Down:"), NULL, - plugin_cfg.vol_down); - - - label = gtk_label_new (NULL); - gtk_label_set_markup (GTK_LABEL (label), _("<b>Player:</b>")); - frame = gtk_frame_new (NULL); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, TRUE, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_container_add (GTK_CONTAINER (frame), alignment); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); - vbox = gtk_vbox_new (FALSE, 2); - gtk_container_add (GTK_CONTAINER (alignment), vbox); - label = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), - _("<i>Configure keys which control the player.</i>")); - table = gtk_table_new (3, 3, FALSE); - gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); - gtk_table_set_col_spacings (GTK_TABLE (table), 2); - gtk_table_set_row_spacings (GTK_TABLE (table), 2); - - add_event_controls(table, &controls->jump_to_file, 0, _("Jump to File:"), NULL, - plugin_cfg.jump_to_file); - - add_event_controls(table, &controls->toggle_win, 1, _("Toggle Player Windows:"), NULL, - plugin_cfg.toggle_win); - - add_event_controls(table, &controls->show_aosd, 2, _("Show On-Screen-Display:"), - _("For this, the Audacious OSD plugin must be activated."), - plugin_cfg.show_aosd); - - button_box = gtk_hbutton_box_new ( ); - gtk_box_pack_start (GTK_BOX (main_vbox), button_box, FALSE, TRUE, 6); - gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_END); - gtk_box_set_spacing (GTK_BOX (button_box), 4); - - button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); - gtk_container_add (GTK_CONTAINER (button_box), button); - g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (cancel_callback), controls); - - button = gtk_button_new_from_stock (GTK_STOCK_OK); - gtk_container_add (GTK_CONTAINER (button_box), button); - g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (ok_callback), controls); - - gtk_widget_show_all (GTK_WIDGET (window)); -} -/* configuration window end */ - -static void about (void) -{ - static GtkWidget *dialog; - - dialog = audacious_info_dialog (_("About Global Hotkey Plugin"), - _("Global Hotkey Plugin\n" - "Control the player with global key combinations or multimedia keys.\n\n" - "Copyright (C) 2007-2008 Sascha Hlusiak <contact@saschahlusiak.de>\n\n" - "Contributers include:\n" - "Copyright (C) 2006-2007 Vladimir Paskov <vlado.paskov@gmail.com>\n" - "Copyright (C) 2000-2002 Ville Syrjälä <syrjala@sci.fi>\n" - " Bryn Davies <curious@ihug.com.au>\n" - " Jonathan A. Davis <davis@jdhouse.org>\n" - " Jeremy Tan <nsx@nsx.homeip.net>\n\n" - ), - _("OK"), TRUE, NULL, NULL); - - gtk_signal_connect(GTK_OBJECT(dialog), "destroy", - GTK_SIGNAL_FUNC(gtk_widget_destroyed), &dialog); -} - -/* Clear keys */ -static void clear_keyboard (GtkWidget *widget, gpointer data) -{ - KeyControls *spins = (KeyControls*)data; - spins->hotkey.key = 0; - spins->hotkey.mask = 0; - spins->hotkey.type = TYPE_KEY; - set_keytext(spins->keytext, 0, 0, TYPE_KEY); -} - -void cancel_callback (GtkWidget *widget, gpointer data) -{ - if (loaded) - { - grab_keys (); - } - if (data) g_free(data); - - gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); -} - -void ok_callback (GtkWidget *widget, gpointer data) -{ - ConfigurationControls *controls= (ConfigurationControls*)data; - - plugin_cfg.play = controls->play.hotkey; - plugin_cfg.pause = controls->pause.hotkey; - plugin_cfg.stop= controls->stop.hotkey; - plugin_cfg.prev_track= controls->prev_track.hotkey; - plugin_cfg.next_track = controls->next_track.hotkey; - plugin_cfg.forward = controls->forward.hotkey; - plugin_cfg.backward = controls->backward.hotkey; - plugin_cfg.vol_up= controls->vol_up.hotkey; - plugin_cfg.vol_down = controls->vol_down.hotkey; - plugin_cfg.mute = controls->mute.hotkey; - plugin_cfg.jump_to_file= controls->jump_to_file.hotkey; - plugin_cfg.toggle_win = controls->toggle_win.hotkey; - plugin_cfg.show_aosd = controls->show_aosd.hotkey; - - save_config ( ); - - if (loaded) - { - grab_keys (); - } - - if (data) g_free(data); - - gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget))); -} - -/* - * plugin cleanup - */ static void cleanup (void) { if (!loaded) return; @@ -1140,97 +347,7 @@ loaded = FALSE; } -/* grab required keys */ -static void ungrab_key(HotkeyConfiguration hotkey) +gboolean is_loaded (void) { - unsigned int modifier = hotkey.mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - - if (hotkey.key == 0) return; - - if (hotkey.type == TYPE_KEY) - { - XUngrabKey (xdisplay, hotkey.key, modifier, x_root_window); - - if (modifier == AnyModifier) - return; - - if (numlock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); - - if (capslock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); - - if (scrolllock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); - - if (numlock_mask && capslock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); - - if (numlock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); - - if (capslock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); - - if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); - } - if (hotkey.type == TYPE_MOUSE) - { - XUngrabButton (xdisplay, hotkey.key, modifier, x_root_window); - - if (modifier == AnyModifier) - return; - - if (numlock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask, x_root_window); - - if (capslock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask, x_root_window); - - if (scrolllock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | scrolllock_mask, x_root_window); - - if (numlock_mask && capslock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask, x_root_window); - - if (numlock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | scrolllock_mask, x_root_window); - - if (capslock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | capslock_mask | scrolllock_mask, x_root_window); - - if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey.key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); - } + return loaded; } - -static void ungrab_keys () -{ - XErrorHandler old_handler = 0; - - if (!grabbed) return; - if (!xdisplay) return; - - XSync(xdisplay, False); - old_handler = XSetErrorHandler (x11_error_handler); - - ungrab_key(plugin_cfg.mute); - ungrab_key(plugin_cfg.vol_up); - ungrab_key(plugin_cfg.vol_down); - ungrab_key(plugin_cfg.play); - ungrab_key(plugin_cfg.pause); - ungrab_key(plugin_cfg.stop); - ungrab_key(plugin_cfg.prev_track); - ungrab_key(plugin_cfg.next_track); - ungrab_key(plugin_cfg.jump_to_file); - ungrab_key(plugin_cfg.forward); - ungrab_key(plugin_cfg.backward); - ungrab_key(plugin_cfg.toggle_win); - ungrab_key(plugin_cfg.show_aosd); - - XSync(xdisplay, False); - XSetErrorHandler (old_handler); - - grabbed = 0; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotkey/plugin.h Sun Jan 20 14:52:44 2008 +0100 @@ -0,0 +1,40 @@ +#ifndef _PLUGIN_H_INCLUDED_ +#define _PLUGIN_H_INCLUDED_ + +#include <glib.h> + +#define TYPE_KEY 0 +#define TYPE_MOUSE 1 + +typedef struct { + gint key, mask; + gint type; +} HotkeyConfiguration; + +typedef struct { + gint vol_increment; + gint vol_decrement; + + /* keyboard */ + HotkeyConfiguration mute; + HotkeyConfiguration vol_down; + HotkeyConfiguration vol_up; + HotkeyConfiguration play; + HotkeyConfiguration stop; + HotkeyConfiguration pause; + HotkeyConfiguration prev_track; + HotkeyConfiguration next_track; + HotkeyConfiguration jump_to_file; + HotkeyConfiguration toggle_win; + HotkeyConfiguration forward; + HotkeyConfiguration backward; + HotkeyConfiguration show_aosd; +} PluginConfig; + +void load_config (void); +void save_config (void); +PluginConfig* get_config(void); +gboolean is_loaded (void); +gboolean handle_keyevent(int keycode, int state, int type); + +#endif