2002-04-25 03:59:56 +00:00
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2002-03-23 04:39:24 +00:00
/* gnome-settings-keyboard.c
*
* Copyright <EFBFBD> 2001 Ximian , Inc .
*
2002-04-25 03:59:56 +00:00
* Written by Jody Goldberg < jody @ gnome . org >
2002-03-23 04:39:24 +00:00
*
* 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 ; either version 2 , or ( at your option )
* any later 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 . , 59 Temple Place - Suite 330 , Boston , MA
* 02111 - 1307 , USA .
*/
# include "config.h"
2004-01-12 20:37:03 +00:00
# include <libgnome/gnome-i18n.h>
2002-03-23 04:39:24 +00:00
# include <gdk/gdk.h>
# include <gdk/gdkx.h>
# include <gconf/gconf-client.h>
2004-02-16 17:32:53 +00:00
# include <libgnome/gnome-help.h>
2002-03-23 04:39:24 +00:00
# include "gnome-settings-accessibility-keyboard.h"
# include "gnome-settings-daemon.h"
# ifdef HAVE_X11_EXTENSIONS_XKB_H
# include <X11 / XKBlib.h>
# include <X11 / extensions / XKBstr.h>
2002-03-29 22:30:40 +00:00
# define CONFIG_ROOT " / desktop / gnome / accessibility / keyboard"
2002-03-23 04:39:24 +00:00
2002-04-25 03:59:56 +00:00
# undef DEBUG_ACCESSIBILITY
2002-03-29 06:19:22 +00:00
# ifdef DEBUG_ACCESSIBILITY
# define d(str) fprintf (stderr, str)
# else
# define d(str) do { } while (0)
# endif
2002-04-11 22:37:52 +00:00
static int xkbEventBase ;
2004-01-12 20:37:03 +00:00
static GtkWidget * ax_slowkeys_dialog = NULL ;
static GtkWidget * ax_slowkeys_dialog_hbox = NULL ;
static GtkWidget * ax_stickykeys_dialog = NULL ;
static GtkWidget * ax_stickykeys_dialog_hbox = NULL ;
static gboolean stickykeys_shortcut_val ;
static gboolean slowkeys_shortcut_val ;
2002-04-11 22:37:52 +00:00
static gboolean
xkb_enabled ( void )
{
static gboolean initialized = 0 ;
static gboolean have_xkb = 0 ;
int opcode , errorBase , major , minor ;
if ( initialized )
return have_xkb ;
gdk_error_trap_push ( ) ;
have_xkb = XkbQueryExtension ( GDK_DISPLAY ( ) ,
& opcode , & xkbEventBase , & errorBase , & major , & minor )
& & XkbUseExtension ( GDK_DISPLAY ( ) , & major , & minor ) ;
XSync ( GDK_DISPLAY ( ) , FALSE ) ;
gdk_error_trap_pop ( ) ;
return have_xkb ;
}
static XkbDescRec *
get_xkb_desc_rec ( void )
{
2002-04-23 18:27:19 +00:00
XkbDescRec * desc ;
Status status = Success ; /* Any bogus value, to suppress warning */
2002-04-11 22:37:52 +00:00
if ( ! xkb_enabled ( ) )
return NULL ;
gdk_error_trap_push ( ) ;
desc = XkbGetMap ( GDK_DISPLAY ( ) , XkbAllMapComponentsMask , XkbUseCoreKbd ) ;
if ( desc ! = NULL ) {
desc - > ctrls = NULL ;
status = XkbGetControls ( GDK_DISPLAY ( ) , XkbAllControlsMask , desc ) ;
}
XSync ( GDK_DISPLAY ( ) , FALSE ) ;
gdk_error_trap_pop ( ) ;
g_return_val_if_fail ( desc ! = NULL , NULL ) ;
g_return_val_if_fail ( desc - > ctrls ! = NULL , NULL ) ;
2002-04-23 18:27:19 +00:00
g_return_val_if_fail ( status = = Success , NULL ) ;
2002-04-11 22:37:52 +00:00
return desc ;
}
2002-03-23 04:39:24 +00:00
static int
get_int ( GConfClient * client , char const * key )
{
int res = gconf_client_get_int ( client , key , NULL ) ;
if ( res < = 0 )
res = 1 ;
return res ;
}
2002-10-08 16:38:20 +00:00
static gboolean
set_int ( GConfClient * client , GConfChangeSet * cs ,
char const * key , int val )
2002-03-23 04:39:24 +00:00
{
2002-09-11 13:24:23 +00:00
gconf_change_set_set_int ( cs , key , val ) ;
2004-01-12 20:37:03 +00:00
# ifdef DEBUG_ACCESSIBILITY
2002-10-08 16:38:20 +00:00
if ( val ! = gconf_client_get_int ( client , key , NULL ) ) {
g_warning ( " %s changed " , key ) ;
}
2004-01-12 20:37:03 +00:00
# endif
2002-10-08 16:38:20 +00:00
return val ! = gconf_client_get_int ( client , key , NULL ) ;
2002-03-23 04:39:24 +00:00
}
2002-10-08 16:38:20 +00:00
static gboolean
set_bool ( GConfClient * client , GConfChangeSet * cs ,
gboolean in_gconf , char const * key , int val )
2002-03-23 04:39:24 +00:00
{
2004-01-12 20:37:03 +00:00
gboolean bval = ( val ! = 0 ) ;
if ( in_gconf | | bval ) {
gconf_change_set_set_bool ( cs , key , bval ? TRUE : FALSE ) ;
# ifdef DEBUG_ACCESSIBILITY
if ( bval ! = gconf_client_get_bool ( client , key , NULL ) ) {
d ( " %s changed " , key ) ;
return TRUE ;
2002-10-08 16:38:20 +00:00
}
2004-01-12 20:37:03 +00:00
# endif
return ( bval ! = gconf_client_get_bool ( client , key , NULL ) ) ;
2002-10-08 16:38:20 +00:00
}
return FALSE ;
2002-03-23 04:39:24 +00:00
}
2002-04-25 03:59:56 +00:00
static unsigned long
set_clear ( gboolean flag , unsigned long value , unsigned long mask )
{
if ( flag )
return value | mask ;
return value & ~ mask ;
}
static gboolean
set_ctrl_from_gconf ( XkbDescRec * desc , GConfClient * client ,
char const * key , unsigned long mask , gboolean flag )
{
gboolean result = flag & & gconf_client_get_bool ( client , key , NULL ) ;
desc - > ctrls - > enabled_ctrls =
set_clear ( result , desc - > ctrls - > enabled_ctrls , mask ) ;
return result ;
}
2002-03-23 04:39:24 +00:00
static void
set_server_from_gconf ( GConfEntry * ignored )
{
GConfClient * client = gconf_client_get_default ( ) ;
2002-04-11 22:37:52 +00:00
XkbDescRec * desc ;
2002-04-25 03:59:56 +00:00
gboolean enable_accessX ;
2002-04-10 23:30:45 +00:00
2002-04-11 22:37:52 +00:00
desc = get_xkb_desc_rec ( ) ;
if ( ! desc ) {
d ( " No XKB present \n " ) ;
return ;
2002-04-11 21:54:10 +00:00
}
2002-03-23 04:39:24 +00:00
/* general */
2002-04-25 03:59:56 +00:00
enable_accessX = gconf_client_get_bool ( client , CONFIG_ROOT " /enable " , NULL ) ;
desc - > ctrls - > enabled_ctrls = set_clear ( enable_accessX ,
desc - > ctrls - > enabled_ctrls ,
XkbAccessXKeysMask | XkbAccessXFeedbackMask ) ;
if ( set_ctrl_from_gconf ( desc , client , CONFIG_ROOT " /timeout_enable " ,
2002-09-11 13:24:23 +00:00
XkbAccessXTimeoutMask , enable_accessX ) ) {
2002-04-25 03:59:56 +00:00
desc - > ctrls - > ax_timeout = get_int ( client ,
CONFIG_ROOT " /timeout " ) ;
2002-09-11 13:24:23 +00:00
/* disable only the master flag via the server we will disable
* the rest on the rebound without affecting gconf state
* don ' t change the option flags at all .
*/
desc - > ctrls - > axt_ctrls_mask = \
XkbAccessXKeysMask |
XkbAccessXFeedbackMask ;
desc - > ctrls - > axt_ctrls_values = 0 ;
desc - > ctrls - > axt_opts_mask = 0 ;
}
2002-09-10 04:04:20 +00:00
desc - > ctrls - > ax_options = set_clear ( enable_accessX & &
gconf_client_get_bool ( client , CONFIG_ROOT " /feature_state_change_beep " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask ) ;
2002-03-23 04:39:24 +00:00
/* bounce keys */
2002-04-25 03:59:56 +00:00
if ( set_ctrl_from_gconf ( desc , client , CONFIG_ROOT " /bouncekeys_enable " ,
XkbBounceKeysMask , enable_accessX ) ) {
desc - > ctrls - > debounce_delay = get_int ( client ,
CONFIG_ROOT " /bouncekeys_delay " ) ;
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /bouncekeys_beep_reject " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_BKRejectFBMask ) ;
}
2002-03-23 04:39:24 +00:00
/* mouse keys */
2002-04-25 03:59:56 +00:00
if ( set_ctrl_from_gconf ( desc , client , CONFIG_ROOT " /mousekeys_enable " ,
XkbMouseKeysMask | XkbMouseKeysAccelMask , enable_accessX ) ) {
desc - > ctrls - > mk_interval = 100 ; /* msec between mousekey events */
desc - > ctrls - > mk_curve = 50 ;
/* We store pixels / sec, XKB wants pixels / event */
desc - > ctrls - > mk_max_speed = get_int ( client ,
CONFIG_ROOT " /mousekeys_max_speed " ) / ( 1000 / desc - > ctrls - > mk_interval ) ;
if ( desc - > ctrls - > mk_max_speed < = 0 )
desc - > ctrls - > mk_max_speed = 1 ;
desc - > ctrls - > mk_time_to_max = get_int ( client , /* events before max */
CONFIG_ROOT " /mousekeys_accel_time " ) / desc - > ctrls - > mk_interval ;
if ( desc - > ctrls - > mk_time_to_max < = 0 )
desc - > ctrls - > mk_time_to_max = 1 ;
desc - > ctrls - > mk_delay = get_int ( client , /* ms before 1st event */
CONFIG_ROOT " /mousekeys_init_delay " ) ;
}
2002-03-23 04:39:24 +00:00
/* slow keys */
2002-04-25 03:59:56 +00:00
if ( set_ctrl_from_gconf ( desc , client , CONFIG_ROOT " /slowkeys_enable " ,
XkbSlowKeysMask , enable_accessX ) ) {
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /slowkeys_beep_press " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_SKPressFBMask ) ;
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /slowkeys_beep_accept " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_SKAcceptFBMask ) ;
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /slowkeys_beep_reject " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_SKRejectFBMask ) ;
desc - > ctrls - > slow_keys_delay = get_int ( client ,
CONFIG_ROOT " /slowkeys_delay " ) ;
2002-06-12 13:50:21 +00:00
/* anything larger than 500 seems to loose all keyboard input */
if ( desc - > ctrls - > slow_keys_delay > 500 )
desc - > ctrls - > slow_keys_delay = 500 ;
2002-04-25 03:59:56 +00:00
}
2002-03-23 04:39:24 +00:00
/* sticky keys */
2002-04-25 03:59:56 +00:00
if ( set_ctrl_from_gconf ( desc , client , CONFIG_ROOT " /stickykeys_enable " ,
XkbStickyKeysMask , enable_accessX ) ) {
desc - > ctrls - > ax_options | = XkbAX_LatchToLockMask ;
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /stickykeys_two_key_off " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_TwoKeysMask ) ;
desc - > ctrls - > ax_options = set_clear (
gconf_client_get_bool ( client , CONFIG_ROOT " /stickykeys_modifier_beep " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_StickyKeysFBMask ) ;
}
2002-03-23 04:39:24 +00:00
/* toggle keys */
2002-04-25 03:59:56 +00:00
desc - > ctrls - > ax_options = set_clear ( enable_accessX & &
gconf_client_get_bool ( client , CONFIG_ROOT " /togglekeys_enable " , NULL ) ,
desc - > ctrls - > ax_options , XkbAX_IndicatorFBMask ) ;
2002-03-23 04:39:24 +00:00
2002-05-22 21:08:19 +00:00
/*
2002-04-25 03:59:56 +00:00
fprintf ( stderr , " CHANGE to : 0x%x \n " , desc - > ctrls - > enabled_ctrls ) ;
fprintf ( stderr , " CHANGE to : 0x%x (2) \n " , desc - > ctrls - > ax_options ) ;
2002-05-22 21:08:19 +00:00
*/
2002-03-23 04:39:24 +00:00
2002-09-11 13:24:23 +00:00
gdk_error_trap_push ( ) ;
2002-04-25 03:59:56 +00:00
XkbSetControls ( GDK_DISPLAY ( ) ,
XkbSlowKeysMask |
XkbBounceKeysMask |
XkbStickyKeysMask |
XkbMouseKeysMask |
XkbMouseKeysAccelMask |
XkbAccessXKeysMask |
XkbAccessXTimeoutMask |
XkbAccessXFeedbackMask |
XkbControlsEnabledMask ,
desc ) ;
2002-04-10 23:30:45 +00:00
XSync ( GDK_DISPLAY ( ) , FALSE ) ;
2002-03-30 03:25:26 +00:00
gdk_error_trap_pop ( ) ;
2004-01-12 20:37:03 +00:00
}
static gboolean
ax_response_callback ( gint response_id , guint revert_controls_mask , gboolean enabled )
{
GConfClient * client = gconf_client_get_default ( ) ;
GError * err = NULL ;
gboolean success ;
switch ( response_id )
{
case GTK_RESPONSE_REJECT :
case GTK_RESPONSE_CANCEL :
/* we're reverting, so we invert sense of 'enabled' flag */
d ( " cancelling AccessX request " ) ;
if ( revert_controls_mask = = XkbStickyKeysMask )
{
success = gconf_client_set_bool ( client , CONFIG_ROOT " /stickykeys_enable " , ! enabled , & err ) ;
if ( err ! = NULL )
g_error_free ( err ) ;
}
if ( revert_controls_mask = = XkbSlowKeysMask )
{
success = gconf_client_set_bool ( client , CONFIG_ROOT " /slowkeys_enable " , ! enabled , & err ) ;
if ( err ! = NULL )
g_error_free ( err ) ;
}
gconf_client_suggest_sync ( client , NULL ) ;
set_server_from_gconf ( NULL ) ;
break ;
case GTK_RESPONSE_HELP :
gnome_help_display_desktop ( NULL ,
" user-guide " ,
2004-02-12 14:23:03 +00:00
" user-guide.xml " ,
2004-01-12 20:37:03 +00:00
" goscustaccess-6 " ,
& err ) ;
if ( err ! = NULL ) {
GtkWidget * error_dialog = gtk_message_dialog_new ( NULL ,
0 ,
GTK_MESSAGE_ERROR ,
GTK_BUTTONS_CLOSE ,
2004-02-16 17:32:53 +00:00
_ ( " There was an error displaying help: %s " ) ,
2004-01-12 20:37:03 +00:00
err - > message ) ;
g_signal_connect ( G_OBJECT ( error_dialog ) ,
" response " ,
G_CALLBACK ( gtk_widget_destroy ) , NULL ) ;
gtk_window_set_resizable ( GTK_WINDOW ( error_dialog ) , FALSE ) ;
gtk_widget_show ( error_dialog ) ;
g_error_free ( err ) ;
}
return FALSE ;
default :
break ;
}
return TRUE ;
}
static void
ax_stickykeys_response ( GtkDialog * dialog , gint response_id , gpointer data )
{
gboolean * enabled = data ;
if ( ax_response_callback ( response_id , XkbStickyKeysMask , * enabled ) )
{
gtk_widget_destroy ( ax_stickykeys_dialog ) ;
ax_stickykeys_dialog = NULL ;
}
}
static void
ax_slowkeys_response ( GtkDialog * dialog , gint response_id , gpointer data )
{
gboolean * enabled = data ;
if ( ax_response_callback ( response_id , XkbSlowKeysMask , * enabled ) )
{
gtk_widget_destroy ( ax_slowkeys_dialog ) ;
ax_slowkeys_dialog = NULL ;
}
}
static GtkWidget *
warning_dialog_post ( GtkWidget * dialog , GtkWidget * * hbox , GCallback response ,
gboolean * enabled , gchar * title , gchar * user_action_string , gchar * query )
{
GtkWidget * label ;
2005-01-11 23:48:10 +00:00
gchar * label_markup_string = g_strconcat ( " <span weight= \" bold \" size= \" larger \" > " ,
query , " </span> \n \n " , user_action_string , NULL ) ;
2004-01-12 20:37:03 +00:00
if ( ! dialog )
{
dialog = gtk_dialog_new_with_buttons ( title , NULL , 0 ,
GTK_STOCK_CANCEL ,
GTK_RESPONSE_REJECT ,
GTK_STOCK_HELP ,
GTK_RESPONSE_HELP ,
GTK_STOCK_OK ,
GTK_RESPONSE_OK ,
NULL ) ;
g_signal_connect ( G_OBJECT ( dialog ) ,
" response " ,
G_CALLBACK ( response ) ,
enabled ) ;
}
else
{
gtk_widget_destroy ( * hbox ) ;
}
* hbox = gtk_hbox_new ( FALSE , 10 ) ;
gtk_container_add ( GTK_CONTAINER ( * hbox ) , gtk_image_new_from_stock ( GTK_STOCK_DIALOG_WARNING , GTK_ICON_SIZE_DIALOG ) ) ;
label = gtk_label_new ( NULL ) ;
gtk_label_set_line_wrap ( GTK_LABEL ( label ) , TRUE ) ;
gtk_label_set_markup ( GTK_LABEL ( label ) , label_markup_string ) ;
g_free ( label_markup_string ) ;
gtk_container_add ( GTK_CONTAINER ( * hbox ) , label ) ;
gtk_container_add ( GTK_CONTAINER ( GTK_DIALOG ( dialog ) - > vbox ) , * hbox ) ;
gtk_widget_show_all ( dialog ) ;
return dialog ;
}
static void
ax_slowkeys_warning_dialog_post ( gboolean enabled )
{
slowkeys_shortcut_val = enabled ;
2004-02-24 17:33:40 +00:00
ax_slowkeys_dialog = warning_dialog_post ( ax_slowkeys_dialog ,
& ax_slowkeys_dialog_hbox ,
( GCallback ) ax_slowkeys_response ,
& slowkeys_shortcut_val ,
_ ( " Slow Keys Alert " ) ,
_ ( " You just held down the Shift key for 8 seconds. This is the shortcut for the Slow Keys feature, which affects the way your keyboard works. " ) ,
enabled ? _ ( " Do you want to activate Slow Keys? " ) :
_ ( " Do you want to deactivate Slow Keys? " ) ) ;
2004-01-12 20:37:03 +00:00
}
static void
ax_stickykeys_warning_dialog_post ( gboolean enabled )
{
stickykeys_shortcut_val = enabled ;
ax_stickykeys_dialog = warning_dialog_post ( ax_stickykeys_dialog ,
& ax_stickykeys_dialog_hbox ,
( GCallback ) ax_stickykeys_response ,
& stickykeys_shortcut_val ,
_ ( " Sticky Keys Alert " ) ,
enabled ? _ ( " You just pressed the Shift key 5 times in a row. This is the shortcut for the Sticky Keys feature, which affects the way your keyboard works. " ) :
2004-01-13 02:13:50 +00:00
_ ( " You just pressed two keys at once, or pressed the Shift key 5 times in a row. This turns off the Sticky Keys feature, which affects the way your keyboard works. " ) ,
2004-01-12 20:37:03 +00:00
enabled ? _ ( " Do you want to activate Sticky Keys? " ) :
2004-02-16 17:55:09 +00:00
_ ( " Do you want to deactivate Sticky Keys? " ) ) ;
2002-03-23 04:39:24 +00:00
}
static void
set_gconf_from_server ( GConfEntry * ignored )
{
2002-08-15 17:54:10 +00:00
gboolean in_gconf ;
2002-03-23 04:39:24 +00:00
GConfClient * client = gconf_client_get_default ( ) ;
2002-09-11 13:24:23 +00:00
GConfChangeSet * cs = gconf_change_set_new ( ) ;
2002-08-15 17:54:10 +00:00
XkbDescRec * desc = get_xkb_desc_rec ( ) ;
2004-01-12 20:37:03 +00:00
gboolean changed = FALSE , slowkeys_changed , stickykeys_changed ;
2002-03-23 04:39:24 +00:00
2002-04-11 22:37:52 +00:00
if ( ! desc ) {
d ( " No XKB present \n " ) ;
return ;
}
2002-04-10 23:30:45 +00:00
2002-05-22 21:08:19 +00:00
/*
2004-01-12 20:37:03 +00:00
fprintf ( stderr , " changed to : 0x%x \n " , desc - > ctrls - > enabled_ctrls ) ;
fprintf ( stderr , " changed to : 0x%x (2) \n " , desc - > ctrls - > ax_options ) ;
2002-05-22 21:08:19 +00:00
*/
2002-03-23 04:39:24 +00:00
2002-08-15 17:54:10 +00:00
/* always toggle this irrespective of the state */
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /enable " ,
2002-04-25 03:59:56 +00:00
desc - > ctrls - > enabled_ctrls & ( XkbAccessXKeysMask | XkbAccessXFeedbackMask ) ) ;
2002-08-15 17:54:10 +00:00
/* if master is disabled in gconf do not change gconf state of subordinates
* to match the server . However , we should enable the master if one of the subordinates
* get enabled .
*/
in_gconf = gconf_client_get_bool ( client , CONFIG_ROOT " /enable " , NULL ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /feature_state_change_beep " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & ( XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask ) ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /timeout_enable " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > enabled_ctrls & XkbAccessXTimeoutMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /timeout " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_timeout ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /bouncekeys_enable " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > enabled_ctrls & XkbBounceKeysMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /bouncekeys_delay " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > debounce_delay ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /bouncekeys_beep_reject " ,
2002-04-25 03:59:56 +00:00
desc - > ctrls - > ax_options & XkbAX_BKRejectFBMask ) ;
2002-03-23 04:39:24 +00:00
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /mousekeys_enable " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > enabled_ctrls & XkbMouseKeysMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /mousekeys_max_speed " ,
2002-04-25 03:59:56 +00:00
desc - > ctrls - > mk_max_speed * ( 1000 / desc - > ctrls - > mk_interval ) ) ;
2002-03-29 17:21:23 +00:00
/* NOTE : mk_time_to_max is measured in events not time */
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /mousekeys_accel_time " ,
2002-03-29 17:21:23 +00:00
desc - > ctrls - > mk_time_to_max * desc - > ctrls - > mk_interval ) ;
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /mousekeys_init_delay " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > mk_delay ) ;
2004-01-12 20:37:03 +00:00
slowkeys_changed = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /slowkeys_enable " ,
desc - > ctrls - > enabled_ctrls & XkbSlowKeysMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /slowkeys_beep_press " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & XkbAX_SKPressFBMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /slowkeys_beep_accept " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & XkbAX_SKAcceptFBMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /slowkeys_beep_reject " ,
2002-04-25 03:59:56 +00:00
desc - > ctrls - > ax_options & XkbAX_SKRejectFBMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_int ( client , cs , CONFIG_ROOT " /slowkeys_delay " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > slow_keys_delay ) ;
2004-01-12 20:37:03 +00:00
stickykeys_changed = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /stickykeys_enable " ,
desc - > ctrls - > enabled_ctrls & XkbStickyKeysMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /stickykeys_two_key_off " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & XkbAX_TwoKeysMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , TRUE , CONFIG_ROOT " /stickykeys_modifier_beep " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & XkbAX_StickyKeysFBMask ) ;
2002-10-08 16:38:20 +00:00
changed | = set_bool ( client , cs , in_gconf , CONFIG_ROOT " /togglekeys_enable " ,
2002-03-23 04:39:24 +00:00
desc - > ctrls - > ax_options & XkbAX_IndicatorFBMask ) ;
2004-01-12 20:37:03 +00:00
if ( ! changed & & stickykeys_changed ^ slowkeys_changed )
{
/*
* sticky or slowkeys has changed , singly , without our intervention .
* 99 % chance this is due to a keyboard shortcut being used .
* we need to detect via this hack until we get
* XkbAXN_AXKWarning notifications working ( probable XKB bug ) ,
* at which time we can directly intercept such shortcuts instead .
* See cb_xkb_event_filter ( ) below .
*/
/* sanity check: are keyboard shortcuts available? */
if ( desc - > ctrls - > enabled_ctrls & XkbAccessXKeysMask )
{
if ( slowkeys_changed )
ax_slowkeys_warning_dialog_post ( desc - > ctrls - > enabled_ctrls & XkbSlowKeysMask ) ;
else
ax_stickykeys_warning_dialog_post ( desc - > ctrls - > enabled_ctrls & XkbStickyKeysMask ) ;
}
}
changed | = ( stickykeys_changed | slowkeys_changed ) ;
2002-10-08 16:38:20 +00:00
if ( changed ) {
2004-01-14 06:41:31 +00:00
gconf_client_commit_change_set ( client , cs , FALSE , NULL ) ;
gconf_client_suggest_sync ( client , NULL ) ;
2002-10-08 16:38:20 +00:00
}
2002-09-11 13:24:23 +00:00
gconf_change_set_unref ( cs ) ;
2002-03-23 04:39:24 +00:00
}
static GdkFilterReturn
2002-04-25 03:59:56 +00:00
cb_xkb_event_filter ( GdkXEvent * xevent , GdkEvent * ignored1 , gpointer ignored2 )
2002-03-23 04:39:24 +00:00
{
2002-04-25 03:59:56 +00:00
XEvent * xev = ( XEvent * ) xevent ;
XkbEvent * xkbEv = ( XkbEvent * ) xevent ;
2004-01-12 20:37:03 +00:00
2002-04-25 03:59:56 +00:00
if ( xev - > xany . type = = ( xkbEventBase + XkbEventCode ) & &
xkbEv - > any . xkb_type = = XkbControlsNotify ) {
2004-01-12 20:37:03 +00:00
d ( " Someone changed XKB state \n " ) ;
set_gconf_from_server ( NULL ) ;
}
else if ( xev - > xany . type = = ( xkbEventBase + XkbEventCode ) & &
xkbEv - > any . xkb_type = = XkbAccessXNotify ) {
if ( xkbEv - > accessx . detail = = XkbAXN_AXKWarning ) {
d ( " About to turn on an AccessX feature from the keyboard! " ) ;
/*
* TODO : when XkbAXN_AXKWarnings start working , we need to
* invoke ax_keys_warning_dialog_run here instead of in
* set_gconf_from_server ( ) .
*/
}
2002-03-23 04:39:24 +00:00
}
return GDK_FILTER_CONTINUE ;
}
void
2002-10-08 16:38:20 +00:00
gnome_settings_accessibility_keyboard_load ( GConfClient * client )
2002-03-23 04:39:24 +00:00
{
2002-10-08 16:38:20 +00:00
static gboolean has_filter = FALSE ;
2004-01-12 20:37:03 +00:00
guint event_mask = XkbControlsNotifyMask ;
# ifdef DEBUG_ACCESSIBILITY
event_mask = XkbControlsNotifyMask | XkbAccessXNotifyMask ) ; /* make default when AXN_AXKWarning works */
# endif
2002-04-11 22:37:52 +00:00
if ( ! xkb_enabled ( ) )
return ;
2002-03-23 04:39:24 +00:00
2002-10-08 16:38:20 +00:00
/* be sure to init before starting to monitor the server */
set_server_from_gconf ( NULL ) ;
/* be careful not to install multipled filters */
if ( has_filter )
return ;
2002-03-30 04:52:52 +00:00
gdk_error_trap_push ( ) ;
2002-03-23 04:39:24 +00:00
XkbSelectEvents ( GDK_DISPLAY ( ) ,
2004-01-12 20:37:03 +00:00
XkbUseCoreKbd ,
event_mask ,
event_mask ) ;
2002-03-30 04:52:52 +00:00
2002-04-10 23:30:45 +00:00
XSync ( GDK_DISPLAY ( ) , FALSE ) ;
2002-03-30 04:52:52 +00:00
gdk_error_trap_pop ( ) ;
2004-01-12 20:37:03 +00:00
gdk_window_add_filter ( NULL ,
& cb_xkb_event_filter , NULL ) ;
2002-11-01 03:42:18 +00:00
}
2002-03-23 04:39:24 +00:00
2002-11-01 03:42:18 +00:00
void
gnome_settings_accessibility_keyboard_init ( GConfClient * client )
{
2002-03-23 04:39:24 +00:00
gnome_settings_daemon_register_callback ( CONFIG_ROOT , & set_server_from_gconf ) ;
}
# else
void
2002-10-08 16:38:20 +00:00
gnome_settings_accessibility_keyboard_load ( GConfClient * client )
2002-03-23 04:39:24 +00:00
{
g_warning ( " Unsupported in this build " ) ;
}
void
2002-10-08 16:38:20 +00:00
gnome_settings_accessibility_keyboard_init ( GConfClient * client )
2002-03-23 04:39:24 +00:00
{
}
2002-11-01 03:42:18 +00:00
# endif