view src/hotkey/gui.c @ 3063:6a6a731fdaf8

crossfade-ng: More sane defaults.
author William Pitcock <nenolod@atheme.org>
date Fri, 24 Apr 2009 06:24:24 -0500
parents 3134a0987162
children
line wrap: on
line source

/*
 *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <config.h>

#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>

#include <audlegacy/plugin.h>
#include <audlegacy/i18n.h>

#include "plugin.h"
#include "gui.h"
#include "grab.h"

typedef struct _KeyControls {
	GtkWidget *keytext;
	GtkWidget *table;
	GtkWidget *button;
	GtkWidget *combobox;

	HotkeyConfiguration hotkey;
	struct _KeyControls *next, *prev, *first;
} KeyControls;


static void clear_keyboard (GtkWidget *widget, gpointer data);
static void add_callback (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 gchar* event_desc[EVENT_MAX] = {
	[EVENT_PREV_TRACK] = N_("Previous Track"),
	[EVENT_PLAY] = N_("Play"),
	[EVENT_PAUSE] = N_("Pause/Resume"),
	[EVENT_STOP] = N_("Stop"),
	[EVENT_NEXT_TRACK] = N_("Next Track"),
	[EVENT_FORWARD] = N_("Forward 5 Seconds"),
	[EVENT_BACKWARD] = N_("Rewind 5 Seconds"),
	[EVENT_MUTE] = N_("Mute"),
	[EVENT_VOL_UP] = N_("Volume Up"),
	[EVENT_VOL_DOWN] = N_("Volume Down"),
	[EVENT_JUMP_TO_FILE] = N_("Jump to File"),
	[EVENT_TOGGLE_WIN] = N_("Toggle Player Windows"),
	[EVENT_SHOW_AOSD] = N_("Show On-Screen-Display")
};


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;
	if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE;
	if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE;
	if (event->keyval == GDK_ISO_Left_Tab)
	{
		set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type);
		return FALSE;
	}
	if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE;
	if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) 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;
		if (controls->next == NULL)
			add_callback (NULL, (gpointer) controls);
		else gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext));
	}

	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 (!gtk_widget_is_focus(widget)) return FALSE;
	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);
	if (controls->next == NULL)
		add_callback (NULL, (gpointer) controls);

	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);
	if (controls->next == NULL)
		add_callback (NULL, (gpointer) controls);
	return TRUE;
}

KeyControls* add_event_controls(KeyControls* list,
				GtkWidget *table,
				int row,
				HotkeyConfiguration *hotkey)
{
	KeyControls *controls;
	int i;

	controls = (KeyControls*) g_malloc(sizeof(KeyControls));
	controls->next = NULL;
	controls->prev = list;
	controls->first = list->first;
	controls->table = table;
	list->next = controls;

	if (hotkey)
	{
		controls->hotkey.key = hotkey->key;
		controls->hotkey.mask = hotkey->mask;
		controls->hotkey.type = hotkey->type;
		controls->hotkey.event = hotkey->event;
		if (controls->hotkey.key == 0)
			controls->hotkey.mask = 0;
	} else {
		controls->hotkey.key = 0;
		controls->hotkey.mask = 0;
		controls->hotkey.type = TYPE_KEY;
		controls->hotkey.event = 0;
	}

	controls->combobox = gtk_combo_box_new_text();
	for (i=0;i<EVENT_MAX;i++)
	{
		gtk_combo_box_append_text( GTK_COMBO_BOX(controls->combobox), _(event_desc[i]) );
	}
	gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), controls->hotkey.event);
	gtk_table_attach (GTK_TABLE (table), controls->combobox, 0, 1, row, row+1,
			(GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0);


	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, controls->hotkey.key, controls->hotkey.mask, controls->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);


	controls->button = gtk_button_new();
	gtk_button_set_image( GTK_BUTTON(controls->button),
                        gtk_image_new_from_stock( GTK_STOCK_DELETE , GTK_ICON_SIZE_BUTTON));
	gtk_table_attach (GTK_TABLE (table), controls->button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
	g_signal_connect (G_OBJECT (controls->button), "clicked",
			G_CALLBACK (clear_keyboard), controls);

	gtk_widget_grab_focus(GTK_WIDGET(controls->keytext));
	return controls;
}

void show_configure ()
{
	KeyControls *first_controls, *current_controls;
	GtkWidget *window;
	GtkWidget *main_vbox, *hbox;
	GtkWidget *alignment;
	GtkWidget *frame;
	GtkWidget *label;
	GtkWidget *image;
	GtkWidget *table;
	GtkWidget *button_box, *button;
	PluginConfig* plugin_cfg;
	HotkeyConfiguration *hotkey, temphotkey;
	int i;

	load_config ( );

	plugin_cfg = get_config();

	ungrab_keys();

	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);
	gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DIALOG);
	gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
	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.\nYou can also bind mouse buttons."));
	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), _("Hotkeys:"));
	frame = gtk_frame_new (NULL);
	gtk_frame_set_label_widget (GTK_FRAME (frame), label);
	gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
	alignment = gtk_alignment_new (0, 0, 1, 0);
	gtk_container_add (GTK_CONTAINER (frame), alignment);
	gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3);

	table = gtk_table_new (1, 3, FALSE);
	gtk_container_add (GTK_CONTAINER (alignment), table);

	gtk_table_set_col_spacings (GTK_TABLE (table), 2);
	gtk_table_set_row_spacings (GTK_TABLE (table), 0);

	label = gtk_label_new (NULL);
	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),
			_("<b>Action:</b>"));
	gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
			(GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0);

	label = gtk_label_new (NULL);
	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),
			_("<b>Key Binding:</b>"));
	gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
			(GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0);


	hotkey = &(plugin_cfg->first);
	i = 1;
	first_controls = (KeyControls*) g_malloc(sizeof(KeyControls));
	first_controls->next = NULL;
	first_controls->prev = NULL;
	first_controls->table = table;
	first_controls->button = NULL;
	first_controls->combobox = NULL;
	first_controls->keytext = NULL;
	first_controls->first = first_controls;
	first_controls->hotkey.key = 0;
	first_controls->hotkey.mask = 0;
	first_controls->hotkey.event = 0;
	first_controls->hotkey.type = TYPE_KEY;
	current_controls = first_controls;
	if (hotkey -> key != 0)
	{
		while (hotkey)
		{
			current_controls = add_event_controls(current_controls, table, i, hotkey);
			hotkey = hotkey->next;
			i++;
		}
	}
	temphotkey.key = 0;
	temphotkey.mask = 0;
	temphotkey.type = TYPE_KEY;
	if (current_controls != first_controls)
		temphotkey.event = current_controls->hotkey.event+1;
	else temphotkey.event = 0;
	if (temphotkey.event >= EVENT_MAX) temphotkey.event = 0;
	add_event_controls(current_controls, table, i, &temphotkey);



	hbox = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);

	button_box = gtk_hbutton_box_new ( );
	gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, TRUE, 0);
	gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START);
	gtk_box_set_spacing (GTK_BOX (button_box), 4);

	button = gtk_button_new_from_stock (GTK_STOCK_ADD);
	gtk_container_add (GTK_CONTAINER (button_box), button);
	g_signal_connect (G_OBJECT (button), "clicked",
			G_CALLBACK (add_callback), first_controls);

	button_box = gtk_hbutton_box_new ( );
	gtk_box_pack_start (GTK_BOX (hbox), button_box, TRUE, TRUE, 0);
	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), NULL);

	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), first_controls);

	g_signal_connect (G_OBJECT (window), "destroy",
		G_CALLBACK (destroy_callback), first_controls);

	gtk_widget_show_all (GTK_WIDGET (window));
}

static void clear_keyboard (GtkWidget *widget, gpointer data)
{
	KeyControls *controls= (KeyControls*)data;
	if ((controls->next == NULL) && (controls->prev->keytext == NULL))
	{
		controls->hotkey.key = 0;
		controls->hotkey.mask = 0;
		controls->hotkey.type = TYPE_KEY;
		set_keytext(controls->keytext, 0, 0, TYPE_KEY);
		gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), 0);
		return;
	}

	if (controls->prev)
	{
		KeyControls* c;
		GtkWidget* table;
		int row;

		gtk_widget_destroy(GTK_WIDGET(controls->button));
		gtk_widget_destroy(GTK_WIDGET(controls->keytext));
		gtk_widget_destroy(GTK_WIDGET(controls->combobox));

		row=0;
		c = controls->first;
		while (c) {
			if (c == controls) break;
			row++;
			c = c->next;
		}
		c = controls->next;
		controls->prev->next = controls->next;
		if (controls->next)
			controls->next->prev = controls->prev;
		g_free(controls);
		if (c) table = c->table; else table = NULL;
		while (c)
		{
			g_object_ref(c->combobox);
			g_object_ref(c->keytext);
			g_object_ref(c->button);

			gtk_container_remove( GTK_CONTAINER(c->table) , c->combobox);
			gtk_container_remove( GTK_CONTAINER(c->table) , c->keytext);
			gtk_container_remove( GTK_CONTAINER(c->table) , c->button);

			gtk_table_attach (GTK_TABLE (c->table), c->combobox, 0, 1, row, row+1,
					(GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0);
			gtk_table_attach (GTK_TABLE (c->table), c->keytext, 1, 2, row, row+1,
					(GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (GTK_EXPAND), 0, 0);
			gtk_table_attach (GTK_TABLE (c->table), c->button, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);

			g_object_unref(c->combobox);
			g_object_unref(c->keytext);
			g_object_unref(c->button);

			c = c->next;
			row++;
		}
		if (table)
			gtk_widget_show_all (GTK_WIDGET (table));

		return;
	}
}

void add_callback (GtkWidget *widget, gpointer data)
{
	KeyControls* controls = (KeyControls*)data;
	HotkeyConfiguration temphotkey;
	int count;
	if (controls == NULL) return;
	if ((controls->next == NULL)&&(controls->hotkey.event+1 == EVENT_MAX)) return;
	controls = controls->first;
	if (controls == NULL) return;
	count = 1;
	while (controls->next) {
		controls = controls->next;
		count = count + 1;
	}
	temphotkey.key = 0;
	temphotkey.mask = 0;
	temphotkey.type = TYPE_KEY;
	temphotkey.event = controls->hotkey.event+1;
	if (temphotkey.event >= EVENT_MAX) temphotkey.event = 0;
	gtk_table_resize(GTK_TABLE(controls->table), count, 3);
	add_event_controls(controls, controls->table, count, &temphotkey);
	gtk_widget_show_all (GTK_WIDGET (controls->table));
}

void destroy_callback (GtkWidget *widget, gpointer data)
{
	KeyControls* controls = (KeyControls*)data;
	if (is_loaded())
	{
		grab_keys ();
	}
	while (controls) {
		KeyControls *old;
		old = controls;
		controls = controls->next;
		g_free(old);
	}
}

void cancel_callback (GtkWidget *widget, gpointer data)
{
	gtk_widget_destroy (gtk_widget_get_toplevel (GTK_WIDGET (widget)));
}

void ok_callback (GtkWidget *widget, gpointer data)
{
	KeyControls *controls = (KeyControls*)data;
	PluginConfig* plugin_cfg = get_config();
	HotkeyConfiguration *hotkey;

	hotkey = &(plugin_cfg->first);
	hotkey = hotkey->next;
	while (hotkey)
	{
		HotkeyConfiguration * old;
		old = hotkey;
		hotkey = hotkey->next;
		g_free(old);
	}
	plugin_cfg->first.next = NULL;
	plugin_cfg->first.key = 0;
	plugin_cfg->first.event = 0;
	plugin_cfg->first.mask = 0;

	hotkey = &(plugin_cfg->first);
	while (controls)
	{
		if (controls->hotkey.key) {
			if (hotkey->key) {
				hotkey->next = g_new(HotkeyConfiguration, 1);
				hotkey = hotkey->next;
				hotkey->next = NULL;
			}
			hotkey->key = controls->hotkey.key;
			hotkey->mask = controls->hotkey.mask;
			hotkey->event = gtk_combo_box_get_active( GTK_COMBO_BOX(controls->combobox) );
			hotkey->type = controls->hotkey.type;
		}
		controls = controls->next;
	}

	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);
}