Index: keyboard_plugin.c =================================================================== --- keyboard_plugin.c (revision 22011) +++ keyboard_plugin.c (working copy) @@ -79,6 +79,9 @@ 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 int repeat_delay = 500; static int repeat_rate = 30; @@ -159,6 +162,46 @@ } static void +toggle_sticky() +{ +#ifdef USE_XKB + if (xkbpresent) + { + XkbDescPtr xkb = XkbAllocKeyboard (); + if (xkb) + { + gdk_error_trap_push (); + XkbGetControls (GDK_DISPLAY (), XkbAllControlsMask, xkb); + + if(sticky_key) + xkb->ctrls->enabled_ctrls |= (XkbStickyKeysMask | XkbAccessXKeysMask); + else + xkb->ctrls->enabled_ctrls &= ~(XkbStickyKeysMask | XkbAccessXKeysMask); + + 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; + + XkbSetControls (GDK_DISPLAY (), XkbControlsEnabledMask | XkbStickyKeysMask, 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; @@ -320,6 +363,35 @@ } static void +cb_checkbutton_sticky_changed (GtkWidget * widget, gpointer user_data) +{ + KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data; + McsPlugin *mcs_plugin = dialog->mcs_plugin; + + sticky_key = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbutton_sticky)); + if(sticky_key) + { + gtk_widget_set_sensitive(dialog->checkbutton_sticky_ltl, TRUE); + gtk_widget_set_sensitive(dialog->checkbutton_sticky_tk, TRUE); + } + else + { + 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); + gtk_widget_set_sensitive(dialog->checkbutton_sticky_ltl, FALSE); + gtk_widget_set_sensitive(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)); + toggle_sticky(); + mcs_manager_set_int (mcs_plugin->manager, "Key/Sticky", 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_notify (mcs_plugin->manager, CHANNEL2); + write_options (mcs_plugin); +} + +static void cb_checkbutton_repeat_changed (GtkWidget * widget, gpointer user_data) { KeyboardMcsDialog *dialog = (KeyboardMcsDialog *) user_data; @@ -595,6 +667,42 @@ gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), nth++), label); gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); + 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); + + frame = xfce_framebox_new (_("Sticky keys"), FALSE); + gtk_widget_show (frame); + gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, TRUE, 0); + + vbox = gtk_vbox_new (FALSE, 5); + gtk_widget_show (vbox); + xfce_framebox_add (XFCE_FRAMEBOX (frame), vbox); + + 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); + + label = gtk_label_new (_("Accessability")); + 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); @@ -641,6 +749,9 @@ 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_sticky_changed), dialog); + g_signal_connect (G_OBJECT (dialog->checkbutton_sticky_ltl), "toggled", G_CALLBACK (cb_checkbutton_sticky_changed), dialog); + g_signal_connect (G_OBJECT (dialog->checkbutton_sticky_tk), "toggled", G_CALLBACK (cb_checkbutton_sticky_changed), dialog); } static void @@ -806,6 +917,39 @@ mcs_manager_set_int (mcs_plugin->manager, "Key/RepeatRate", CHANNEL2, repeat_rate); } + setting = mcs_manager_setting_lookup (mcs_plugin->manager, "Key/Sticky", CHANNEL2); + if(setting) + { + sticky_key = (setting->data.v_int ? TRUE : FALSE); + } + else + { + sticky_key = FALSE; + mcs_manager_set_int (mcs_plugin->manager, "Key/Sticky", 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); + } + #ifdef USE_XF86MISC #ifdef DEBUG g_message ("Querying XF86Misc extension"); @@ -855,6 +999,7 @@ #endif set_repeat_rate (repeat_delay, repeat_rate); + toggle_sticky(); #if 0 /* I fail to see why we need to save the options here, during startup... */ Index: shortcuts_plugin.h =================================================================== --- shortcuts_plugin.h (revision 22011) +++ shortcuts_plugin.h (working copy) @@ -29,6 +29,9 @@ GtkWidget *checkbutton_blink; GtkWidget *checkbutton_repeat; + GtkWidget *checkbutton_sticky; + GtkWidget *checkbutton_sticky_ltl; + GtkWidget *checkbutton_sticky_tk; GtkWidget *scale_repeat_rate; GtkWidget *scale_repeat_delay; GtkWidget *scale_blink_time;