/*
        This program 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; You may only use version 2 of the License,
        you have no option to use any other version.

        This program 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 this program; if not, write to the Free Software
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

        gnome theme-switcher capplet - (c) Jonathan Blandford <jrb@gnome.org>
        xfce4 mcs plugin   - (c) 2002 Olivier Fourdan

 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <X11/Xlib.h>

#ifdef USE_XF86MISC
#include <X11/extensions/xf86misc.h>
#endif

#ifdef USE_XKB
#include <X11/XKBlib.h>
#endif

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

#include <libxfce4mcs/mcs-common.h>
#include <libxfce4mcs/mcs-manager.h>
#include <libxfce4util/libxfce4util.h>
#include <xfce-mcs-manager/manager-plugin.h>
#include <libxfcegui4/libxfcegui4.h>

#include "shortcuts_plugin.h"
#include "plugins/gtk_common/gtk_common.h"

#define PLUGIN_NAME "keyboard"
#define DEFAULT_MAP "Default"

#define ON 1
#define OFF 0
#define ALL -1

#define MAX_ELEMENTS_BEFORE_SCROLLING 6

static void create_channel (McsPlugin * mcs_plugin);
static gboolean write_options (McsPlugin * mcs_plugin);
static void run_dialog (McsPlugin * mcs_plugin);

static gboolean setting_model = FALSE;
static gboolean initial_scroll = TRUE;
static gboolean is_running = FALSE;
static gchar *current_key_map = NULL;
static gboolean cursor_blink = TRUE;
static int cursor_blink_time = 500;
static gboolean repeat_key = TRUE;
static gboolean sticky_key = FALSE;
static gboolean sticky_key_ltl = FALSE;
static gboolean sticky_key_tk = FALSE;

static gboolean bounce_key = FALSE;
static int debounce_delay = 200;

static gboolean slow_key = FALSE;
static int slow_keys_delay = 200;

static int repeat_delay = 500;
static int repeat_rate = 30;

#ifdef USE_XF86MISC
static gboolean miscpresent = FALSE;
#endif

#ifdef USE_XKB
static gboolean xkbpresent = FALSE;
#endif

static void
set_repeat (int key, int auto_repeat_mode)
{
    XKeyboardControl values;
    values.auto_repeat_mode = auto_repeat_mode;

    gdk_flush ();
    gdk_error_trap_push ();
    if (key != ALL)
    {
        values.key = key;
        XChangeKeyboardControl (GDK_DISPLAY (), KBKey | KBAutoRepeatMode, &values);
    }
    else
    {
        XChangeKeyboardControl (GDK_DISPLAY (), KBAutoRepeatMode, &values);
    }
    gdk_flush ();
    gdk_error_trap_pop ();
}

static void
set_repeat_rate (int delay, int rate)
{
#ifdef USE_XF86MISC
    XF86MiscKbdSettings values;
#endif

    g_return_if_fail (rate > 0);
    g_return_if_fail (delay > 0);

#ifdef USE_XF86MISC
    if (miscpresent)
    {
        gdk_flush ();
        gdk_error_trap_push ();
        XF86MiscGetKbdSettings (GDK_DISPLAY (), &values);
        values.delay = delay;
        values.rate = rate;
        XF86MiscSetKbdSettings (GDK_DISPLAY (), &values);
        gdk_flush ();
        gdk_error_trap_pop ();
    }
#endif

#ifdef USE_XKB
    if (xkbpresent)
    {
        XkbDescPtr xkb = XkbAllocKeyboard ();
        if (xkb)
        {
            gdk_error_trap_push ();
            XkbGetControls (GDK_DISPLAY (), XkbRepeatKeysMask, xkb);
            xkb->ctrls->repeat_delay = delay;
            xkb->ctrls->repeat_interval = 1000 / rate;
            XkbSetControls (GDK_DISPLAY (), XkbRepeatKeysMask, xkb);
            XFree (xkb);
            gdk_flush ();
            gdk_error_trap_pop ();
        }
        else
        {
            g_warning ("XkbAllocKeyboard() returned null pointer");
        }
    }
#endif
}

static void
toggle_accessx()
{
#ifdef USE_XKB
    if (xkbpresent)
    {
        XkbDescPtr xkb = XkbAllocKeyboard ();
        if (xkb)
        {
            gdk_error_trap_push ();
            XkbGetControls (GDK_DISPLAY (), XkbAllControlsMask, xkb);

            /* Slow keys */
            if(slow_key)
            {
                xkb->ctrls->enabled_ctrls |= XkbSlowKeysMask;
                xkb->ctrls->slow_keys_delay = slow_keys_delay;
            }
            else
                xkb->ctrls->enabled_ctrls &= ~XkbSlowKeysMask;

            /* Bounce keys */
            if(bounce_key)
            {
                xkb->ctrls->enabled_ctrls |= XkbBounceKeysMask;
                xkb->ctrls->debounce_delay = debounce_delay;
            }
            else
                xkb->ctrls->enabled_ctrls &= ~XkbBounceKeysMask;

            /* Sticky keys */
            if(sticky_key)
                xkb->ctrls->enabled_ctrls |= XkbStickyKeysMask;
            else
                xkb->ctrls->enabled_ctrls &= ~XkbStickyKeysMask;

            if(sticky_key_ltl)
                xkb->ctrls->ax_options |= XkbAX_LatchToLockMask;
            else
                xkb->ctrls->ax_options &= ~XkbAX_LatchToLockMask;

            if(sticky_key_tk)
                xkb->ctrls->ax_options |= XkbAX_TwoKeysMask;
            else
                xkb->ctrls->ax_options &= ~XkbAX_TwoKeysMask;

            /* If any option is set, enable AccessXKeys, otherwise: don't */
            if(sticky_key || bounce_key || slow_key)
                xkb->ctrls->enabled_ctrls |= XkbAccessXKeysMask;
            else
                xkb->ctrls->enabled_ctrls &= ~XkbAccessXKeysMask;

            XkbSetControls (GDK_DISPLAY (), XkbControlsEnabledMask | XkbStickyKeysMask | XkbBounceKeysMask | XkbSlowKeysMask, xkb);
            XFree (xkb);
            gdk_flush ();
            gdk_error_trap_pop ();
        }
        else
        {
            g_warning ("XkbAllocKeyboard() returned null pointer");
        }
    }
#endif
}

static void
theme_selection_changed (GtkTreeSelection * selection, gpointer data)
{
    GtkTreeModel *model;
    gchar *new_key_theme;
    GtkTreeIter iter;
    McsPlugin *mcs_plugin;

    if (setting_model)
        return;

    mcs_plugin = (McsPlugin *) data;

    if (gtk_tree_selection_get_selected (selection, &model, &iter))
    {
        gtk_tree_model_get (model, &iter, THEME_NAME_COLUMN, &new_key_theme, -1);
    }
    else
    {
        new_key_theme = NULL;
    }

    if (new_key_theme != NULL)
    {
        if (current_key_map && strcmp (current_key_map, new_key_theme))
        {
            g_free (current_key_map);
            current_key_map = new_key_theme;
            mcs_manager_set_string (mcs_plugin->manager, "Gtk/KeyThemeName", CHANNEL1, current_key_map);
            mcs_manager_notify (mcs_plugin->manager, CHANNEL1);
            write_options (mcs_plugin);
        }
    }
}

static void
read_themes (KeyboardMcsDialog * dialog)
{
    static GList *gtk_theme_list = NULL;
    GList *list;
    GtkTreeModel *model;
    GtkTreeView *tree_view;
    gint i = 0;
    gboolean current_key_map_found = FALSE;
    GtkTreeRowReference *row_ref = NULL;

    gtk_theme_list = theme_common_get_list (gtk_theme_list);
    tree_view = GTK_TREE_VIEW (dialog->treeview_maps);
    model = gtk_tree_view_get_model (tree_view);

    setting_model = TRUE;
    gtk_list_store_clear (GTK_LIST_STORE (model));

    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->theme_swindow), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
    gtk_widget_set_size_request (dialog->theme_swindow, -1, -1);

    for (list = gtk_theme_list; list; list = list->next)
    {
        ThemeInfo *info = list->data;
        GtkTreeIter iter;

        if (!info->has_keybinding)
            continue;

        gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_NAME_COLUMN, info->name, -1);

        if (strcmp (current_key_map, info->name) == 0)
        {
            GtkTreePath *path = gtk_tree_model_get_path (model, &iter);
            row_ref = gtk_tree_row_reference_new (model, path);
            gtk_tree_path_free (path);
            current_key_map_found = TRUE;
        }

        if (i == MAX_ELEMENTS_BEFORE_SCROLLING)
        {
            GtkRequisition rectangle;
            gtk_widget_size_request (GTK_WIDGET (tree_view), &rectangle);
            gtk_widget_set_size_request (dialog->theme_swindow, -1, rectangle.height);
            gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dialog->theme_swindow), 
                                            GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
        }
        i++;
    }

    if (!current_key_map_found)
    {
        GtkTreeIter iter;
        GtkTreePath *path;

        gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
        gtk_list_store_set (GTK_LIST_STORE (model), &iter, THEME_NAME_COLUMN, current_key_map, -1);

        path = gtk_tree_model_get_path (model, &iter);
        row_ref = gtk_tree_row_reference_new (model, path);
        gtk_tree_path_free (path);
    }

    if (row_ref)
    {
        GtkTreePath *path;

        path = gtk_tree_row_reference_get_path (row_ref);
        gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);

        if (initial_scroll)
        {
            gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 0.5, 0.0);
            initial_scroll = FALSE;
        }

        gtk_tree_path_free (path);
        gtk_tree_row_reference_free (row_ref);
    }
    setting_model = FALSE;
}

static gint
sort_func (GtkTreeModel * model, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data)
{
    gchar *a_str = NULL;
    gchar *b_str = NULL;

    gtk_tree_model_get (model, a, 0, &a_str, -1);
    gtk_tree_model_get (model, b, 0, &b_str, -1);

    if (a_str == NULL)
        a_str = g_strdup ("");
    if (b_str == NULL)
        b_str = g_strdup ("");

    if (!strcmp (a_str, DEFAULT_MAP))
        return -1;
    if (!strcmp (b_str, DEFAULT_MAP))
        return 1;

    return g_utf8_collate (a_str, b_str);
}

static void
cb_dialog_response (GtkWidget* widget, gint response_id, KeyboardMcsDialog* dialog)
{
    write_options (dialog->mcs_plugin);
    if (dialog->theme_modified)
    {
        shortcuts_plugin_save_theme (dialog);
    }

    if (response_id == GTK_RESPONSE_HELP)
    {
        g_message ("HELP: TBD");
    }
    else
    {
        is_running = FALSE;
        gtk_widget_destroy (widget);
    }

}

static void
cb_checkbutton_accessx_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    bounce_key = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_bounce));
    gtk_widget_set_sensitive(dialog->scale_debounce_delay, bounce_key);

    slow_key = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_slow));
    gtk_widget_set_sensitive(dialog->scale_slow_keys_delay, slow_key);

    sticky_key = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky));

    gtk_widget_set_sensitive(dialog->checkbutton_sticky_ltl, sticky_key);
    gtk_widget_set_sensitive(dialog->checkbutton_sticky_tk, sticky_key);
    if(!sticky_key) 
    {
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->checkbutton_sticky_ltl), FALSE);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->checkbutton_sticky_tk), FALSE);
    }

    sticky_key_ltl = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky_ltl));
    sticky_key_tk = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky_tk));
    debounce_delay = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_debounce_delay));
    slow_keys_delay = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_slow_keys_delay));

    toggle_accessx();
    mcs_manager_set_int (mcs_plugin->manager, "Key/StickyKeys", CHANNEL2, sticky_key ? 1 : 0);
    mcs_manager_set_int (mcs_plugin->manager, "Key/StickyLatchToLock", CHANNEL2, sticky_key_ltl ? 1 : 0);
    mcs_manager_set_int (mcs_plugin->manager, "Key/StickyTwoKeysDisable", CHANNEL2, sticky_key_tk ? 1 : 0);
    mcs_manager_set_int (mcs_plugin->manager, "Key/BounceKeys", CHANNEL2, bounce_key ? 1 : 0);
    mcs_manager_set_int (mcs_plugin->manager, "Key/SlowKeys", CHANNEL2, slow_key ? 1 : 0);
    mcs_manager_set_int (mcs_plugin->manager, "Key/DeBounceDelay", CHANNEL2, debounce_delay);
    mcs_manager_set_int (mcs_plugin->manager, "Key/SlowKeysDelay", CHANNEL2, slow_keys_delay);
    mcs_manager_notify (mcs_plugin->manager, CHANNEL2);
    write_options (mcs_plugin);
}

static void
cb_scale_accessx_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    debounce_delay = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_debounce_delay));
    slow_keys_delay = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_slow_keys_delay));

    toggle_accessx();
    mcs_manager_set_int (mcs_plugin->manager, "Key/DeBounceDelay", CHANNEL2, debounce_delay);
    mcs_manager_set_int (mcs_plugin->manager, "Key/SlowKeysDelay", CHANNEL2, slow_keys_delay);
}

static void
cb_checkbutton_repeat_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    repeat_key = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_repeat));
    gtk_widget_set_sensitive (dialog->scale_repeat_rate, repeat_key);
    gtk_widget_set_sensitive (dialog->scale_repeat_delay, repeat_key);
    set_repeat (ALL, repeat_key ? ON : OFF);

    mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatKey", CHANNEL2, repeat_key ? 1 : 0);
    mcs_manager_notify (mcs_plugin->manager, CHANNEL2);
    write_options (mcs_plugin);
}

static void
cb_repeatdelay_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    repeat_rate = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_repeat_rate));
    repeat_delay = (int) gtk_range_get_value (GTK_RANGE (dialog->scale_repeat_delay));

    mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatDelay", CHANNEL2, repeat_delay);
    mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatRate", CHANNEL2, repeat_rate);

    set_repeat_rate (repeat_delay, repeat_rate);

    mcs_manager_notify (mcs_plugin->manager, CHANNEL2);
    write_options (mcs_plugin);
}

static void
cb_checkbutton_blink_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    cursor_blink = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_blink));
    gtk_widget_set_sensitive (dialog->scale_blink_time, cursor_blink);

    mcs_manager_set_int (mcs_plugin->manager, "Net/CursorBlink", CHANNEL1, cursor_blink ? 1 : 0);
    mcs_manager_notify (mcs_plugin->manager, CHANNEL1);
    write_options (mcs_plugin);
}

static void
cb_blinktime_changed (GtkWidget * widget, gpointer user_data)
{
    KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data;
    McsPlugin *mcs_plugin = dialog->mcs_plugin;

    cursor_blink_time = 2600 - (int) gtk_range_get_value (GTK_RANGE (dialog->scale_blink_time));
    mcs_manager_set_int (mcs_plugin->manager, "Net/CursorBlinkTime", CHANNEL1, cursor_blink_time);
    mcs_manager_notify (mcs_plugin->manager, CHANNEL1);
    write_options (mcs_plugin);
}

GtkWidget *
accessx_plugin_create(KeyboardMcsDialog *dialog)
{
    GtkWidget *frame;
    GtkWidget *label;
    GtkWidget *vbox;
    GtkWidget *main_vbox = gtk_vbox_new(FALSE, 5);
    gtk_widget_show(main_vbox);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Sticky keys"), vbox);
    gtk_widget_show (frame);
    gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);

    dialog->checkbutton_sticky = gtk_check_button_new_with_mnemonic(_("Enable Sticky keys"));
    gtk_widget_show(dialog->checkbutton_sticky);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->checkbutton_sticky, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky), sticky_key);

    dialog->checkbutton_sticky_ltl = gtk_check_button_new_with_mnemonic(_("Latch To Lock"));
    gtk_widget_show(dialog->checkbutton_sticky_ltl);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->checkbutton_sticky_ltl, FALSE, FALSE, 0);
    gtk_widget_set_sensitive(dialog->checkbutton_sticky_ltl, sticky_key);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky_ltl), sticky_key_ltl);

    dialog->checkbutton_sticky_tk = gtk_check_button_new_with_mnemonic(_("Two Keys Disable"));
    gtk_widget_show(dialog->checkbutton_sticky_tk);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->checkbutton_sticky_tk, FALSE, FALSE, 0);
    gtk_widget_set_sensitive(dialog->checkbutton_sticky_tk, sticky_key);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky_tk), sticky_key_tk);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Slow keys"), vbox);
    gtk_widget_show (frame);
    gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);

    dialog->checkbutton_slow = gtk_check_button_new_with_mnemonic(_("Enable Slow keys"));
    gtk_widget_show(dialog->checkbutton_slow);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->checkbutton_slow, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_slow), slow_key);

    label = gtk_label_new (_("Slow keys delay :"));
    gtk_widget_show (label);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    dialog->scale_slow_keys_delay = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (slow_keys_delay, 10, 500, 10, 10, 0)));
    gtk_widget_show(dialog->scale_slow_keys_delay);
    gtk_scale_set_draw_value (GTK_SCALE (dialog->scale_slow_keys_delay), FALSE);
    gtk_range_set_update_policy (GTK_RANGE (dialog->scale_slow_keys_delay), GTK_UPDATE_DISCONTINUOUS);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->scale_slow_keys_delay, FALSE, FALSE, 0);
    gtk_widget_set_sensitive(dialog->scale_slow_keys_delay, slow_key);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Bounce keys"), vbox);
    gtk_widget_show (frame);
    gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);

    dialog->checkbutton_bounce = gtk_check_button_new_with_mnemonic(_("Enable Bounce keys"));
    gtk_widget_show(dialog->checkbutton_bounce);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->checkbutton_bounce, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_bounce), bounce_key);

    label = gtk_label_new (_("DeBounce delay :"));
    gtk_widget_show (label);
    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    dialog->scale_debounce_delay = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (debounce_delay, 10, 500, 10, 10, 0)));
    gtk_widget_show(dialog->scale_debounce_delay);
    gtk_scale_set_draw_value (GTK_SCALE (dialog->scale_debounce_delay), FALSE);
    gtk_range_set_update_policy (GTK_RANGE (dialog->scale_debounce_delay), GTK_UPDATE_DISCONTINUOUS);
    gtk_box_pack_start(GTK_BOX(vbox), dialog->scale_debounce_delay, FALSE, FALSE, 0);
    gtk_widget_set_sensitive(dialog->scale_debounce_delay, bounce_key);

    return main_vbox;
}

KeyboardMcsDialog *
keyboard_plugin_create_dialog (McsPlugin * mcs_plugin)
{
    KeyboardMcsDialog *dialog;

    GtkWidget *notebook;
    GtkWidget *frame;
    GtkWidget *button;
    GtkWidget *main_hbox;
    GtkWidget *hbox;
    GtkWidget *label;
    GtkWidget *table;
    GtkWidget *left_vbox;
    GtkWidget *vbox;
    GtkWidget *entry;
    GtkWidget *shortcuts_widget;
    GtkWidget *accessx_widget;
    guint nth = 0;
    
    dialog = g_new (KeyboardMcsDialog, 1);

    dialog->mcs_plugin = mcs_plugin;

    dialog->dialog_keyboard = xfce_titled_dialog_new ();

    gtk_window_set_icon_name (GTK_WINDOW (dialog->dialog_keyboard), "xfce4-keyboard");
    gtk_window_set_title (GTK_WINDOW (dialog->dialog_keyboard), _("Keyboard Preferences"));
    gtk_window_set_default_size (GTK_WINDOW (dialog->dialog_keyboard), 440, 200);
    gtk_dialog_set_has_separator (GTK_DIALOG (dialog->dialog_keyboard), FALSE);

    notebook = gtk_notebook_new ();
    gtk_widget_show (GTK_WIDGET(notebook));
    gtk_container_set_border_width (GTK_CONTAINER(notebook), 6);
    gtk_box_pack_start(GTK_BOX (GTK_DIALOG(dialog->dialog_keyboard)->vbox), GTK_WIDGET(notebook), TRUE, TRUE, 0);

    main_hbox = gtk_hbox_new (FALSE, 5);
    gtk_widget_show (main_hbox);
    gtk_container_add (GTK_CONTAINER (notebook), main_hbox);
    gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 5);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Keyboard map"), vbox);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, TRUE, 0);

    hbox = gtk_hbox_new (FALSE, 8);
    gtk_widget_show (hbox);
    gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);

    dialog->theme_swindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_widget_show (dialog->theme_swindow);
    gtk_box_pack_start (GTK_BOX (hbox), dialog->theme_swindow, TRUE, TRUE, 0);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (dialog->theme_swindow), GTK_SHADOW_IN);

    dialog->treeview_maps = gtk_tree_view_new ();
    gtk_widget_show (dialog->treeview_maps);
    gtk_container_add (GTK_CONTAINER (dialog->theme_swindow), dialog->treeview_maps);
    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->treeview_maps), FALSE);

    left_vbox = gtk_vbox_new (FALSE, 0);
    gtk_widget_show (left_vbox);
    gtk_box_pack_start (GTK_BOX (main_hbox), left_vbox, TRUE, TRUE, 0);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Typing Settings"), vbox);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (left_vbox), frame, TRUE, TRUE, 0);

    dialog->checkbutton_repeat = gtk_check_button_new_with_mnemonic (_("Repeat"));
    gtk_widget_show (dialog->checkbutton_repeat);
    gtk_box_pack_start (GTK_BOX (vbox), dialog->checkbutton_repeat, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_repeat), repeat_key);

    table = gtk_table_new (4, 3, FALSE);
    gtk_widget_show (table);
    gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);

    label = xfce_create_small_label (_("Short"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    label = xfce_create_small_label (_("Long"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = xfce_create_small_label (_("Slow"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    label = xfce_create_small_label (_("Fast"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 2, 3, 3, 4, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = gtk_label_new (_("Delay :"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 3, 0, 1, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = gtk_label_new (_("Speed :"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 3, 2, 3, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    dialog->scale_repeat_rate = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (repeat_rate, 10, 500, 10, 10, 0)));
    gtk_widget_show (dialog->scale_repeat_rate);
    gtk_table_attach (GTK_TABLE (table), dialog->scale_repeat_rate, 1, 2, 3, 4, 
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 2);
    gtk_scale_set_draw_value (GTK_SCALE (dialog->scale_repeat_rate), FALSE);
    gtk_range_set_update_policy (GTK_RANGE (dialog->scale_repeat_rate), GTK_UPDATE_DISCONTINUOUS);
    gtk_widget_set_sensitive (dialog->scale_repeat_rate, repeat_key);

    dialog->scale_repeat_delay = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (repeat_delay, 100, 2000, 10, 100, 0)));
    gtk_widget_show (dialog->scale_repeat_delay);
    gtk_table_attach (GTK_TABLE (table), dialog->scale_repeat_delay, 1, 2, 1, 2, 
                      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 2);
    gtk_scale_set_draw_value (GTK_SCALE (dialog->scale_repeat_delay), FALSE);
    gtk_range_set_update_policy (GTK_RANGE (dialog->scale_repeat_delay), GTK_UPDATE_DISCONTINUOUS);
    gtk_widget_set_sensitive (dialog->scale_repeat_delay, repeat_key);

    vbox = gtk_vbox_new (FALSE, 5);
    gtk_widget_show (vbox);

    frame = xfce_create_framebox_with_content (_("Cursor"), vbox);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (left_vbox), frame, TRUE, TRUE, 0);

    dialog->checkbutton_blink = gtk_check_button_new_with_mnemonic (_("Show blinking"));
    gtk_widget_show (dialog->checkbutton_blink);
    gtk_box_pack_start (GTK_BOX (vbox), dialog->checkbutton_blink, FALSE, FALSE, 0);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_blink), cursor_blink);

    table = gtk_table_new (2, 3, FALSE);
    gtk_widget_show (table);
    gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);

    label = gtk_label_new (_("Speed :"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 3, 0, 1, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = xfce_create_small_label (_("Slow"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    label = xfce_create_small_label (_("Fast"));
    gtk_widget_show (label);
    gtk_table_attach (GTK_TABLE (table), label, 2, 3, 1, 2, 
                      (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 2);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    dialog->scale_blink_time = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (CLAMP (2600 - cursor_blink_time, 100, 2500), 
                                      100, 2500, 200, 0, 0)));
    gtk_widget_show (dialog->scale_blink_time);
    gtk_table_attach (GTK_TABLE (table), dialog->scale_blink_time, 1, 2, 1, 2, 
                                 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (GTK_FILL), 0, 2);
    gtk_scale_set_draw_value (GTK_SCALE (dialog->scale_blink_time), FALSE);
    gtk_range_set_update_policy (GTK_RANGE (dialog->scale_blink_time), GTK_UPDATE_DISCONTINUOUS);
    gtk_widget_set_sensitive (dialog->scale_blink_time, cursor_blink);

    entry = gtk_entry_new();
    gtk_widget_show (entry);
    gtk_entry_set_text(GTK_ENTRY(entry), _("Use this entry area to test the settings above."));

    frame = xfce_create_framebox_with_content (_("Test area"), entry);
    gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
    gtk_widget_show (frame);
    gtk_box_pack_start (GTK_BOX (left_vbox), frame, TRUE, TRUE, 0);

    hbox = GTK_DIALOG (dialog->dialog_keyboard)->action_area;
    gtk_widget_show (hbox);
    gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);

    label = gtk_label_new (_("Settings"));
    gtk_widget_show (label);
    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook),
        gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), nth++), label);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);

    shortcuts_widget = shortcuts_plugin_create_dialog (dialog);
    gtk_container_add (GTK_CONTAINER (notebook), shortcuts_widget);
    label = gtk_label_new (_("Shortcuts"));
    gtk_widget_show (label);
    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook),
        gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), nth++), label);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);

    accessx_widget = accessx_plugin_create(dialog);
    gtk_widget_show(accessx_widget);
    gtk_container_add(GTK_CONTAINER(notebook), accessx_widget);
    gtk_container_set_border_width (GTK_CONTAINER (accessx_widget), 5);

    label = gtk_label_new (_("Accessibility"));
    gtk_widget_show (label);
    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook),
        gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), nth++), label);
    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);

    button = gtk_button_new_from_stock ("gtk-help");
    /* gtk_widget_show (button); */
    gtk_dialog_add_action_widget (GTK_DIALOG (dialog->dialog_keyboard), button, GTK_RESPONSE_HELP);
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);

    button = gtk_button_new_from_stock ("gtk-close");
    gtk_widget_show (button);
    gtk_dialog_add_action_widget (GTK_DIALOG (dialog->dialog_keyboard), button, GTK_RESPONSE_CLOSE);
    GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);

    gtk_widget_grab_focus (button);
    gtk_widget_grab_default (button);

    return dialog;
}

static void
keyboard_plugin_setup_dialog (KeyboardMcsDialog * dialog)
{
    GtkTreeModel *model;
    GtkTreeSelection *selection;

    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (dialog->treeview_maps), 
                                                 -1, 
                                                 NULL, 
                                                 gtk_cell_renderer_text_new (), 
                                                 "text", 
                                                 THEME_NAME_COLUMN, 
                                                 NULL);
                                                 
    model = (GtkTreeModel *) gtk_list_store_new (N_COLUMNS, G_TYPE_STRING);
    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (model), 0, sort_func, NULL, NULL);
    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0, GTK_SORT_ASCENDING);
    gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview_maps), model);
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview_maps));
    gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
    g_signal_connect (G_OBJECT (selection), "changed", (GCallback) theme_selection_changed, dialog->mcs_plugin);

    read_themes (dialog);

    g_signal_connect (G_OBJECT (dialog->dialog_keyboard), "response", G_CALLBACK (cb_dialog_response), dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_repeat), "toggled", G_CALLBACK (cb_checkbutton_repeat_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->scale_repeat_rate), "value_changed", (GCallback) cb_repeatdelay_changed, dialog);
    g_signal_connect (G_OBJECT (dialog->scale_repeat_delay), "value_changed", (GCallback) cb_repeatdelay_changed, dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_blink), "toggled", G_CALLBACK (cb_checkbutton_blink_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->scale_blink_time), "value_changed", (GCallback) cb_blinktime_changed, dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_sticky), "toggled", G_CALLBACK (cb_checkbutton_accessx_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_sticky_ltl), "toggled", G_CALLBACK (cb_checkbutton_accessx_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_sticky_tk), "toggled", G_CALLBACK (cb_checkbutton_accessx_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_bounce), "toggled", G_CALLBACK (cb_checkbutton_accessx_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->checkbutton_slow), "toggled", G_CALLBACK (cb_checkbutton_accessx_changed), dialog);
    g_signal_connect (G_OBJECT (dialog->scale_slow_keys_delay), "value_changed", (GCallback) cb_scale_accessx_changed, dialog);
    g_signal_connect (G_OBJECT (dialog->scale_debounce_delay), "value_changed", (GCallback) cb_scale_accessx_changed, dialog);
}

static void
setup_dialog (KeyboardMcsDialog * dialog)
{
    keyboard_plugin_setup_dialog (dialog);
    shortcuts_plugin_setup_dialog (dialog);

    xfce_gtk_window_center_on_monitor_with_pointer (GTK_WINDOW (dialog->dialog_keyboard));
    gdk_x11_window_set_user_time(GTK_WIDGET (dialog->dialog_keyboard)->window, 
            gdk_x11_get_server_time (GTK_WIDGET (dialog->dialog_keyboard)->window));
            
    gtk_widget_show (dialog->dialog_keyboard);
}

McsPluginInitResult
mcs_plugin_init (McsPlugin * mcs_plugin)
{
    /* This is required for UTF-8 at least - Please don't remove it */
    xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");

    create_channel (mcs_plugin);
    mcs_plugin->plugin_name = g_strdup (PLUGIN_NAME);
    /* the button label in the xfce-mcs-manager dialog */
    mcs_plugin->caption = g_strdup (Q_ ("Button Label|Keyboard"));
    mcs_plugin->run_dialog = run_dialog;
    mcs_manager_notify (mcs_plugin->manager, CHANNEL1);
    mcs_plugin->icon = xfce_themed_icon_load ("xfce4-keyboard", 48);
    if (G_LIKELY (mcs_plugin->icon != NULL))
        g_object_set_data_full (G_OBJECT (mcs_plugin->icon), "mcs-plugin-icon-name", g_strdup ("xfce4-keyboard"), g_free);
    
    shortcuts_plugin_init (mcs_plugin);

    return MCS_PLUGIN_INIT_OK;
}

static void
create_channel (McsPlugin * mcs_plugin)
{
    McsSetting *setting;
    gchar *rcfile, *path;
#ifdef USE_XF86MISC
    int major, minor;
#endif
#ifdef USE_XKB
    int xkbmajor = XkbMajorVersion, xkbminor = XkbMinorVersion;
    int xkbopcode, xkbevent, xkberror;
#endif

    path = g_build_filename ("xfce4", RCDIR, RCFILE1, NULL);
    rcfile = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, path);

    if (!rcfile)
    {
        rcfile = xfce_get_userfile (OLD_RCDIR, RCFILE1, NULL);
    }

    if (g_file_test (rcfile, G_FILE_TEST_EXISTS))
    {
        mcs_manager_add_channel_from_file (mcs_plugin->manager, CHANNEL1, rcfile);
    }
    else
    {
        mcs_manager_add_channel (mcs_plugin->manager, CHANNEL1);
    }

    g_free (path);
    g_free (rcfile);

    path = g_build_filename ("xfce4", RCDIR, RCFILE2, NULL);
    rcfile = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, path);

    if (!rcfile)
    {
        rcfile = xfce_get_userfile (OLD_RCDIR, RCFILE2, NULL);
    }

    if (g_file_test (rcfile, G_FILE_TEST_EXISTS))
    {
        mcs_manager_add_channel_from_file (mcs_plugin->manager, CHANNEL2, rcfile);
    }
    else
    {
        mcs_manager_add_channel (mcs_plugin->manager, CHANNEL2);
    }

    g_free (path);
    g_free (rcfile);


    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Gtk/KeyThemeName", CHANNEL1);
    if (setting)
    {
        if (current_key_map)
            g_free (current_key_map);

        current_key_map = g_strdup (setting->data.v_string);
    }
    else
    {
        if (current_key_map)
            g_free (current_key_map);

        current_key_map = g_strdup (DEFAULT_MAP);

        mcs_manager_set_string (mcs_plugin->manager, "Gtk/KeyThemeName", CHANNEL1, current_key_map);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Net/CursorBlink", CHANNEL1);

    if (setting)
        cursor_blink = (setting->data.v_int ? TRUE : FALSE);
    else
    {
        cursor_blink = TRUE;
        mcs_manager_set_int (mcs_plugin->manager, "Net/CursorBlink", CHANNEL1, cursor_blink ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Net/CursorBlinkTime", CHANNEL1);

    if (setting)
        cursor_blink_time = setting->data.v_int;
    else
    {
        cursor_blink_time = 500;
        mcs_manager_set_int (mcs_plugin->manager, "Net/CursorBlinkTime", CHANNEL1, cursor_blink_time);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/RepeatKey", CHANNEL2);

    if (setting)
    {
        repeat_key = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        repeat_key = TRUE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatKey", CHANNEL2, repeat_key ? 1 : 0);
    }

    set_repeat (ALL, repeat_key ? ON : OFF);

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/RepeatDelay", CHANNEL2);

    if (setting)
    {
        repeat_delay = setting->data.v_int;
    }
    else
    {
        repeat_delay = 500;
        mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatDelay", CHANNEL2, repeat_delay);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/RepeatRate", CHANNEL2);
    if (setting)
    {
        repeat_rate = setting->data.v_int;
    }
    else
    {
        repeat_rate = 30;
        mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatRate", CHANNEL2, repeat_rate);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/StickyKeys", CHANNEL2);
    if(setting)
    {
        sticky_key = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        sticky_key = FALSE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/StickyKeys", CHANNEL2, sticky_key ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/StickyLatchToLock", CHANNEL2);
    if(setting)
    {
        sticky_key_ltl = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        sticky_key_ltl = FALSE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/StickyLatchToLock", CHANNEL2, sticky_key_ltl ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/StickyTwoKeysDisable", CHANNEL2);
    if(setting)
    {
        sticky_key_tk = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        sticky_key_tk = FALSE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/StickyTwoKeysDisable", CHANNEL2, sticky_key_tk ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/BounceKeys", CHANNEL2);
    if(setting)
    {
        bounce_key = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        bounce_key = FALSE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/BounceKeys", CHANNEL2, bounce_key ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/DeBounceDelay", CHANNEL2);
    if (setting)
    {
        debounce_delay = setting->data.v_int;
    }
    else
    {
        debounce_delay = 200;
        mcs_manager_set_int (mcs_plugin->manager, "Key/DeBounceDelay", CHANNEL2, debounce_delay);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/SlowKeys", CHANNEL2);
    if(setting)
    {
        slow_key = (setting->data.v_int ? TRUE : FALSE);
    }
    else
    {
        slow_key = FALSE;
        mcs_manager_set_int (mcs_plugin->manager, "Key/SlowKeys", CHANNEL2, slow_key ? 1 : 0);
    }

    setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/SlowKeysDelay", CHANNEL2);
    if (setting)
    {
        slow_keys_delay = setting->data.v_int;
    }
    else
    {
        slow_keys_delay = 200;
        mcs_manager_set_int (mcs_plugin->manager, "Key/SlowKeysDelay", CHANNEL2, slow_keys_delay);
    }

#ifdef USE_XF86MISC
#ifdef DEBUG
    g_message ("Querying XF86Misc extension");
#endif
    if (XF86MiscQueryVersion (GDK_DISPLAY (), &major, &minor))
    {
#ifdef DEBUG
        g_message ("XF86Misc extension found");
#endif
        miscpresent = TRUE;
    }
    else
    {
#ifdef DEBUG
        g_warning ("Your X server does not support XF86Misc extension");
#endif
        miscpresent = FALSE;
    }
#else
#ifdef DEBUG
    g_message ("This build doesn't include support for XF86Misc extension");
#endif
#endif

#ifdef USE_XKB
#ifdef DEBUG
    g_message ("Querying Xkb extension");
#endif
    if (XkbQueryExtension (GDK_DISPLAY (), &xkbopcode, &xkbevent, &xkberror, &xkbmajor, &xkbminor))
    {
#ifdef DEBUG
        g_message ("Xkb extension found");
#endif
        xkbpresent = TRUE;
    }
    else
    {
#ifdef DEBUG
        g_message ("Your X server does not support Xkb extension");
#endif
        xkbpresent = FALSE;
    }
#else
#ifdef DEBUG
    g_warning ("This build doesn't include support for Xkb extension");
#endif
#endif

    set_repeat_rate (repeat_delay, repeat_rate);
    toggle_accessx();

#if 0    
    /* I fail to see why we need to save the options here, during startup... */
    write_options (mcs_plugin);
#endif
}

static gboolean
write_options (McsPlugin * mcs_plugin)
{
    gboolean result = FALSE;
    gchar *rcfile, *path;

    path = g_build_filename ("xfce4", RCDIR, RCFILE1, NULL);
    rcfile = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, path, TRUE);
    if (G_LIKELY (rcfile != NULL))
    {
        result = mcs_manager_save_channel_to_file (mcs_plugin->manager, CHANNEL1, rcfile);
        g_free (rcfile);
    }
    g_free (path);

    path = g_build_filename ("xfce4", RCDIR, RCFILE2, NULL);
    rcfile = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, path, TRUE);
    if (G_LIKELY (rcfile != NULL))
    {
        result &= mcs_manager_save_channel_to_file (mcs_plugin->manager, CHANNEL2, rcfile);
        g_free (rcfile);
    }
    g_free (path);

    shortcuts_plugin_save_settings (mcs_plugin);

    return (result);
}

static void
run_dialog (McsPlugin * mcs_plugin)
{
    static KeyboardMcsDialog *dialog = NULL;

    xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");

    if (is_running)
    {
        if((dialog) && (dialog->dialog_keyboard))
        {
            gtk_window_present(GTK_WINDOW(dialog->dialog_keyboard));
            gtk_window_set_focus (GTK_WINDOW(dialog->dialog_keyboard), NULL);
        }
        return;
    }

    is_running = TRUE;
    dialog = keyboard_plugin_create_dialog (mcs_plugin);
    setup_dialog (dialog);
    shortcuts_plugin_load_theme (dialog);
}

/* macro defined in manager-plugin.h */
MCS_PLUGIN_CHECK_INIT


syntax highlighted by Code2HTML, v. 0.9.1