From ac2dad48917fa7b47239d133e4740e21effa69d5 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 12 Sep 2005 17:20:22 +0000 Subject: [PATCH] Remap buttons on auxillary mice for left-handed mode (bug 314409). 2005-09-12 Ray Strode Remap buttons on auxillary mice for left-handed mode (bug 314409). * configure.in: add check for xinput extension, needed for bug 314409. * gnome-settings-daemon/gnome-settings-mouse.c (supports_xinput_devices): new function to detect XInput Extension (configure_button_layout): new function to set up logical mouse button layout for left or right handed mode (xinput_device_has_buttons): new function to detect if an xinput device has buttons to reconfigure (set_xinput_devices_left_handed): new function to set auxillary mice into left-handed mode (set_left_handed): call set_xinput_devices_left_handed if available --- ChangeLog | 5 + configure.in | 1 + gnome-settings-daemon/ChangeLog | 17 ++ gnome-settings-daemon/gnome-settings-mouse.c | 168 ++++++++++++++++--- 4 files changed, 170 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6148dd793..4d47d0713 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-09-12 Ray Strode + + * configure.in: add check for xinput extension, needed + for bug 314409. + 2005-09-04 Sebastien Bacher * NEWS: update for 2.12.0 diff --git a/configure.in b/configure.in index 35bd23c13..5dd703c11 100644 --- a/configure.in +++ b/configure.in @@ -83,6 +83,7 @@ AC_CHECK_HEADERS([X11/extensions/xf86misc.h], [XF86MISC_LIBS="-lXxf86misc"],[], ]) AC_SUBST(XF86MISC_LIBS) AC_CHECK_HEADERS(X11/extensions/XKB.h) +AC_CHECK_HEADERS(X11/extensions/XInput.h) CPPFLAGS=$savecppflags diff --git a/gnome-settings-daemon/ChangeLog b/gnome-settings-daemon/ChangeLog index 081c8d390..b5928f844 100644 --- a/gnome-settings-daemon/ChangeLog +++ b/gnome-settings-daemon/ChangeLog @@ -1,3 +1,20 @@ +2005-09-12 Ray Strode + + Remap buttons on auxillary mice for left-handed + mode (bug 314409). + + * gnome-settings-mouse.c (supports_xinput_devices): new + function to detect XInput Extension + (configure_button_layout): new function to set up + logical mouse button layout for left or right handed + mode + (xinput_device_has_buttons): new function to detect if + an xinput device has buttons to reconfigure + (set_xinput_devices_left_handed): new function to set + auxillary mice into left-handed mode + (set_left_handed): call set_xinput_devices_left_handed + if available + 2005-08-03 Sebastien Bacher * actions/Makefile.am: fix the build without gstreamer and with alsa, diff --git a/gnome-settings-daemon/gnome-settings-mouse.c b/gnome-settings-daemon/gnome-settings-mouse.c index 825674571..d38246c44 100644 --- a/gnome-settings-daemon/gnome-settings-mouse.c +++ b/gnome-settings-daemon/gnome-settings-mouse.c @@ -1,3 +1,5 @@ +#include + #include #include @@ -6,43 +8,167 @@ #include #include +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H +#include +#endif + #include #include "gnome-settings-locate-pointer.h" #include "gnome-settings-daemon.h" -#define DEFAULT_PTR_MAP_SIZE 128 +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H +static gboolean +supports_xinput_devices (void) +{ + gint op_code, event, error; + + return XQueryExtension (GDK_DISPLAY (), "XInputExtension", + &op_code, &event, &error); +} +#endif + +static void +configure_button_layout (guchar *buttons, + gint n_buttons, + gboolean left_handed) +{ + const gint left_button = 0; + gint right_button; + + /* if the button is higher than 2 (3rd button) then it's + * probably one direction of a scroll wheel or something else + * uninteresting + */ + right_button = MIN (n_buttons - 1, 2); + + if (left_handed) + { + buttons[left_button] = right_button + 1; + buttons[right_button] = left_button + 1; + } + else + { + buttons[left_button] = left_button + 1; + buttons[right_button] = right_button + 1; + } +} + +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H +static gboolean +xinput_device_has_buttons (XDeviceInfo *device_info) +{ + int i; + XAnyClassInfo *class_info; + + class_info = device_info->inputclassinfo; + for (i = 0; i < device_info->num_classes; i++) + { + if (class_info->class == ButtonClass) + { + XButtonInfo *button_info; + + button_info = (XButtonInfo *) class_info; + if (button_info->num_buttons > 0) + return TRUE; + } + + class_info = (XAnyClassInfo *) (((guchar *) class_info) + + class_info->length); + } + return FALSE; +} + +static void +set_xinput_devices_left_handed (gboolean left_handed) +{ + XDeviceInfo *device_info; + gint n_devices; + guchar *buttons; + gsize buttons_capacity = 16; + gint n_buttons; + gint i; + + device_info = XListInputDevices (GDK_DISPLAY (), &n_devices); + + if (n_devices > 0) + buttons = g_new (guchar, buttons_capacity); + else + buttons = NULL; + + for (i = 0; i < n_devices; i++) + { + XDevice *device = NULL; + + if ((device_info[i].use != IsXExtensionDevice) || + (!xinput_device_has_buttons (&device_info[i]))) + continue; + + gdk_error_trap_push (); + + device = XOpenDevice (GDK_DISPLAY (), device_info[i].id); + + if ((gdk_error_trap_pop () != 0) || + (device == NULL)) + continue; + + n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY (), device, + buttons, + buttons_capacity); + + while (n_buttons > buttons_capacity) + { + buttons_capacity = n_buttons; + buttons = (guchar *) g_realloc (buttons, + buttons_capacity * sizeof (guchar)); + + n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY (), device, + buttons, + buttons_capacity); + } + + configure_button_layout (buttons, n_buttons, left_handed); + + XSetDeviceButtonMapping (GDK_DISPLAY (), device, buttons, n_buttons); + XCloseDevice (GDK_DISPLAY (), device); + } + g_free (buttons); + + if (device_info != NULL) + XFreeDeviceList (device_info); +} +#endif static void set_left_handed (gboolean left_handed) { - unsigned char *buttons; - gint n_buttons, i; - gint idx_1 = 0, idx_3 = 1; + guchar *buttons ; + gsize buttons_capacity = 16; + gint n_buttons; - buttons = g_alloca (DEFAULT_PTR_MAP_SIZE); - n_buttons = XGetPointerMapping (GDK_DISPLAY (), buttons, DEFAULT_PTR_MAP_SIZE); - if (n_buttons > DEFAULT_PTR_MAP_SIZE) { - buttons = g_alloca (n_buttons); - n_buttons = XGetPointerMapping (GDK_DISPLAY (), buttons, n_buttons); - } +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H + if (supports_xinput_devices ()) + set_xinput_devices_left_handed (left_handed); +#endif - for (i = 0; i < n_buttons; i++) + buttons = g_new (guchar, buttons_capacity); + n_buttons = XGetPointerMapping (GDK_DISPLAY (), buttons, + (gint) buttons_capacity); + while (n_buttons > buttons_capacity) { - if (buttons[i] == 1) - idx_1 = i; - else if (buttons[i] == ((n_buttons < 3) ? 2 : 3)) - idx_3 = i; + buttons_capacity = n_buttons; + buttons = (guchar *) g_realloc (buttons, + buttons_capacity * sizeof (guchar)); + + n_buttons = XGetPointerMapping (GDK_DISPLAY (), buttons, + (gint) buttons_capacity); } - if ((left_handed && idx_1 < idx_3) || - (!left_handed && idx_1 > idx_3)) - { - buttons[idx_1] = ((n_buttons < 3) ? 2 : 3); - buttons[idx_3] = 1; - } + configure_button_layout (buttons, n_buttons, left_handed); XSetPointerMapping (GDK_DISPLAY (), buttons, n_buttons); + + g_free (buttons); } static void