[Xfce4-commits] r27274 - in xfce4-settings/trunk: . dialogs/keyboard-settings dialogs/mouse-settings xfce4-settings-helper

Nick Schermer nick at xfce.org
Sun Jul 13 17:14:04 CEST 2008


Author: nick
Date: 2008-07-13 15:14:04 +0000 (Sun, 13 Jul 2008)
New Revision: 27274

Added:
   xfce4-settings/trunk/xfce4-settings-helper/pointers.c
   xfce4-settings/trunk/xfce4-settings-helper/pointers.h
Modified:
   xfce4-settings/trunk/ChangeLog
   xfce4-settings/trunk/TODO
   xfce4-settings/trunk/configure.ac.in
   xfce4-settings/trunk/dialogs/keyboard-settings/main.c
   xfce4-settings/trunk/dialogs/mouse-settings/Makefile.am
   xfce4-settings/trunk/dialogs/mouse-settings/main.c
   xfce4-settings/trunk/dialogs/mouse-settings/mouse-dialog.glade
   xfce4-settings/trunk/xfce4-settings-helper/Makefile.am
   xfce4-settings/trunk/xfce4-settings-helper/accessx.c
   xfce4-settings/trunk/xfce4-settings-helper/accessx.h
   xfce4-settings/trunk/xfce4-settings-helper/main.c
   xfce4-settings/trunk/xfce4-settings-helper/xkb.c
   xfce4-settings/trunk/xfce4-settings-helper/xkb.h
Log:
	* dialogs/mouse-settings/mouse-dialog.glade,
	  dialogs/mouse-settings/main.c,
	  dialogs/mouse-settings/Makefile.am,
	  xfce4-settings-helper/pointers.h,
	  xfce4-settings-helper/pointers.c: Merge multi pointer
	  branch code.
	* dialogs/keyboard-settings/main.c: Release the channels
	  after running the dialog.
	* xfce4-settings-helper/accessx.c, 
	  xfce4-settings-helper/accessx.h,
	  xfce4-settings-helper/xkb.c,
	  xfce4-settings-helper/xkb.h: Move code into objects. Will
	  make things look nice and allows the code to cleanup when
	  the objects are released in main.c.
	* xfce4-settings-helper/main.c: Use the objects and do some
	  more checking before running the dialog.
	* xfce4-settings-helper/accessx.c: Make disabling the mouse
	  keys work; don't call channel_get functions when not needed.
	* dialogs/keyboard-settings/main.c: Release the channels after
	  running the dialog, also destroy the dialog after using it.

Modified: xfce4-settings/trunk/ChangeLog
===================================================================
--- xfce4-settings/trunk/ChangeLog	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/ChangeLog	2008-07-13 15:14:04 UTC (rev 27274)
@@ -1,3 +1,26 @@
+2008-07-13	Nick Schermer <nick at xfce.org>
+
+	* dialogs/mouse-settings/mouse-dialog.glade,
+	  dialogs/mouse-settings/main.c,
+	  dialogs/mouse-settings/Makefile.am,
+	  xfce4-settings-helper/pointers.h,
+	  xfce4-settings-helper/pointers.c: Merge multi pointer
+	  branch code.
+	* dialogs/keyboard-settings/main.c: Release the channels
+	  after running the dialog.
+	* xfce4-settings-helper/accessx.c, 
+	  xfce4-settings-helper/accessx.h,
+	  xfce4-settings-helper/xkb.c,
+	  xfce4-settings-helper/xkb.h: Move code into objects. Will
+	  make things look nice and allows the code to cleanup when
+	  the objects are released in main.c.
+	* xfce4-settings-helper/main.c: Use the objects and do some
+	  more checking before running the dialog.
+	* xfce4-settings-helper/accessx.c: Make disabling the mouse
+	  keys work; don't call channel_get functions when not needed.
+	* dialogs/keyboard-settings/main.c: Release the channels after
+	  running the dialog, also destroy the dialog after using it.
+
 2008-07-11	Nick Schermer <nick at xfce.org>
 
 	* dialogs/mouse-settings/mouse-dialog.glade: Add some tooltips

Modified: xfce4-settings/trunk/TODO
===================================================================
--- xfce4-settings/trunk/TODO	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/TODO	2008-07-13 15:14:04 UTC (rev 27274)
@@ -9,8 +9,6 @@
 Mouse settings (Nick)
 ------------------------------------------------------------------------
 
-  * Integrate multi pointer branch.
-  * Make hal and libxcursor an optional dependency.
-  * Check dependency versions of libxi and libxcursor.
-  * Make it work a bit better with onyl 1 pointer.
-  * Move the device information into a separate xfconf channel.
+  * Fixup some of the Makefiles.
+  * Add signal watch to xfce4-setting-helper to quit the main loop when
+    receiving a sigterm.

Modified: xfce4-settings/trunk/configure.ac.in
===================================================================
--- xfce4-settings/trunk/configure.ac.in	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/configure.ac.in	2008-07-13 15:14:04 UTC (rev 27274)
@@ -1,5 +1,5 @@
 dnl
-dnl Copyright (c) 2006
+dnl Copyright (c) 2006 - 2008
 dnl         The Xfce development team. All rights reserved.
 dnl
 dnl Originally written for Xfce by Benedikt Meurer <benny at xfce.org>
@@ -21,53 +21,184 @@
 dnl *******************************************
 m4_define([xfce4_settings_debug_default], [ifelse(xfce4_settings_version_tag(), [svn], [full], [minimum])])
 
+dnl ***************************
+dnl *** Initialize autoconf ***
+dnl ***************************
 AC_COPYRIGHT([Copyright (c) 2008
-        The Xfce development team. All rights reserved.
-
-Written for Xfce by Stephan Arts <stephan at xfce.org>.])
-
+        The Xfce development team. All rights reserved.])
 AC_INIT([xfce4-settings], [xfce4_settings_version], [http://bugzilla.xfce.org/])
 AC_PREREQ([2.50])
+AC_REVISION([$Id])
 
-XFCE4_SETTINGS_VERSION=xfce4_settings_version
-AM_INIT_AUTOMAKE([xfce4-settings], [$XFCE4_SETTINGS_VERSION])
+dnl ***************************
+dnl *** Initialize automake ***
+dnl ***************************
+AM_INIT_AUTOMAKE([1.8 dist-bzip2 tar-ustar])
 AM_CONFIG_HEADER([config.h])
-AM_MAINTAINER_MODE
+AM_MAINTAINER_MODE()
 
-dnl check for UNIX variants
-AC_AIX
-AC_ISC_POSIX
-AC_MINIX
-AM_CONDITIONAL([HAVE_CYGWIN], [test "`uname | grep \"CYGWIN\"`" != ""])
+dnl *******************************
+dnl *** Check for UNIX variants ***
+dnl *******************************
+AC_AIX()
+AC_ISC_POSIX()
+AC_MINIX()
 
-
-dnl check for standard header files
-AC_PROG_CC
+dnl ********************************
+dnl *** Check for basic programs ***
+dnl ********************************
+AC_PROG_CC()
+AC_PROG_LD()
+AC_PROG_INSTALL()
 AC_PROG_INTLTOOL([0.31], [no-xml])
-AC_HEADER_STDC
-AC_CHECK_HEADERS([string.h math.h stdio.h stdlib.h])
 
+dnl **************************
+dnl *** Initialize libtool ***
+dnl **************************
+AC_PROG_LIBTOOL()
 
-dnl Check for i18n support
+dnl **********************************
+dnl *** Check for standard headers ***
+dnl **********************************
+AC_CHECK_HEADERS([errno.h memory.h math.h stdlib.h stdio.h string.h unistd.h])
+
+dnl ******************************
+dnl *** Check for i18n support ***
+dnl ******************************
 XDT_I18N([@LINGUAS@])
 
-
+dnl ***********************************
+dnl *** Check for required packages ***
+dnl ***********************************
+XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.0])
 XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
 XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.12.0])
-XDT_CHECK_PACKAGE([GOBJECT], [gobject-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.12.0])
+XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
+XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.4.0])
+XDT_CHECK_PACKAGE([GLADE], [libglade-2.0], [2.0.0])
+XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [0])
 XDT_CHECK_PACKAGE([DBUS_GLIB], [dbus-glib-1], [0.34])
-XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [0])
-XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.4.0])
-XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
-XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.0])
-XDT_CHECK_OPTIONAL_PACKAGE([GLADE], [libglade-2.0], [2.0.0])
+XDT_CHECK_PACKAGE([XI], [xi], [1.1.0])
+XDT_CHECK_PACKAGE([LIBX11], [x11], [1.1.0])
 
-XDT_CHECK_PACKAGE([LIBNOTIFY], [libnotify], [0.1.3])
+dnl **************************************
+dnl *** Optional support for Libnotify ***
+dnl **************************************
+XDT_CHECK_OPTIONAL_PACKAGE([LIBNOTIFY], [libnotify], [0.1.3],
+                           [libnotify], [Notification support])
 
+dnl ********************************
+dnl *** Optional support for HAL ***
+dnl ********************************
+XDT_CHECK_OPTIONAL_PACKAGE([HAL], [hal], [0.5.0],
+                           [hal], [Hotplugging support])
 
-dnl check for debugging support
-XDT_FEATURE_DEBUG
+dnl ************************************
+dnl *** Optional support for Xcursor ***
+dnl ************************************
+XDT_CHECK_OPTIONAL_PACKAGE([XCURSOR], [xcursor], [1.1.0],
+                           [xcursor], [Cursor themes support])
 
+dnl *************************************
+dnl *** Optional support for Xf86misc ***
+dnl *************************************
+XDT_CHECK_OPTIONAL_PACKAGE([XF86MISC], [libxxf86misc], [0.9.0],
+                           [xf86misc], [Support for the X Miscellaneous extension wire protocol])
+
+dnl ***********************************
+dnl *** Check for debugging support ***
+dnl ***********************************
+AC_ARG_ENABLE([debug],
+AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes/full@:>@], [Turn on debugging @<:@default=xfce4_settings_debug_default@:>@]),
+  [], [enable_debug=xfce4_settings_debug_default])
+AC_MSG_CHECKING([whether to enable debugging support])
+if test x"$enable_debug" = x"full" -o x"$enable_debug" = x"yes"; then
+  dnl Print the result
+  AC_MSG_RESULT([$enable_debug])
+
+  dnl Make sure we detect possible errors (if supported)
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Wall -Werror"
+  AC_MSG_CHECKING([whether $CC accepts -Wall -Werror])
+  AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [
+    AC_MSG_RESULT([yes])
+    PLATFORM_CFLAGS="$PLATFORM_CFLAGS -Wall -Werror"
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+  CFLAGS="$save_CFLAGS"
+
+  dnl Paranoia for --enable-debug=full
+  if test x"$enable_debug" = x"full"; then
+    dnl Enable extensive debugging
+    PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_ENABLE_DEBUG"
+
+    dnl Use -O0 -g3 if the compiler supports it
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -O0 -g3"
+    AC_MSG_CHECKING([whether $CC accepts -O0 -g3])
+    AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [
+      AC_MSG_RESULT([yes])
+      PLATFORM_CFLAGS="$PLATFORM_CFLAGS -O0 -g3"
+    ], [
+      AC_MSG_RESULT([no])
+    ])
+    CFLAGS="$save_CFLAGS"
+  fi
+else
+  dnl Print the result
+  AC_MSG_RESULT([$enable_debug])
+
+  dnl Disable debugging (release build)
+  PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DNDEBUG"
+
+  dnl Disable object cast checks
+  PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_CAST_CHECKS"
+
+  dnl Disable all checks for --enable-debug=no
+  if test x"$enable_debug" = x"no"; then
+    PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS"
+  fi
+fi
+
+dnl **************************************
+dnl *** Check for linker optimizations ***
+dnl **************************************
+AC_MSG_CHECKING([whether $LD accepts --as-needed])
+case `$LD --as-needed -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  LDFLAGS="$LDFLAGS -Wl,--as-needed"
+  AC_MSG_RESULT([yes])
+  ;;
+*)
+  AC_MSG_RESULT([no])
+  ;;
+esac
+AC_MSG_CHECKING([whether $LD accepts -O1])
+case `$LD -O1 -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -Wl,-O1"
+  AC_MSG_RESULT([yes])
+  ;;
+*)
+  AC_MSG_RESULT([no])
+  ;;
+esac
+
+dnl *********************************
+dnl *** Substitute platform flags ***
+dnl *********************************
+AC_MSG_CHECKING([PLATFORM_CPPFLAGS])
+AC_MSG_RESULT([$PLATFORM_CPPFLAGS])
+AC_SUBST([PLATFORM_CPPFLAGS])
+AC_MSG_CHECKING([PLATFORM_CFLAGS])
+AC_MSG_RESULT([$PLATFORM_CFLAGS])
+AC_SUBST([PLATFORM_CFLAGS])
+AC_MSG_CHECKING([PLATFORM_LDFLAGS])
+AC_MSG_RESULT([$PLATFORM_LDFLAGS])
+AC_SUBST([PLATFORM_LDFLAGS])
+
 AC_OUTPUT([
 Makefile
 po/Makefile.in
@@ -80,9 +211,27 @@
 xfce4-settings-manager/Makefile
 ])
 
-echo "----------------------------------------"
-echo "$PACKAGE $VERSION"
-echo ""
-echo "The binary will be installed in $prefix/bin"
-echo ""
-echo "Configure finished, type 'make' to build."
+dnl ***************************
+dnl *** Print configuration ***
+dnl ***************************
+echo
+echo "Build Configuration:"
+echo
+echo "* Installation prefix:       $prefix"
+echo "* Debug Support:             $enable_debug"
+if test x"$LIBNOTIFY_FOUND" = x"yes"; then
+echo "* Libnotify support:         yes"
+else
+echo "* Libnotify support:         no"
+fi
+if test x"$HAL_FOUND" = x"yes"; then
+echo "* HAL support:               yes"
+else
+echo "* HAL support:               no"
+fi
+if test x"$XCURSOR_FOUND" = x"yes"; then
+echo "* Xcursor support:           yes"
+else
+echo "* Xcursor support:           no"
+fi
+echo

Modified: xfce4-settings/trunk/dialogs/keyboard-settings/main.c
===================================================================
--- xfce4-settings/trunk/dialogs/keyboard-settings/main.c	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/dialogs/keyboard-settings/main.c	2008-07-13 15:14:04 UTC (rev 27274)
@@ -479,10 +479,6 @@
   gtk_widget_show_all(dialog);
   gtk_widget_hide(dialog);
 
-  g_object_unref (xsettings_channel);
-  g_object_unref (xkb_channel);
-  g_object_unref (kbd_channel);
-
   return dialog;
 }
 
@@ -523,7 +519,14 @@
   /* Create settings dialog and run it */
   dialog = keyboard_settings_dialog_new_from_xml (gxml);
   gtk_dialog_run(GTK_DIALOG(dialog));
+  
+  gtk_widget_destroy (dialog);
+  
+  g_object_unref (xsettings_channel);
+  g_object_unref (xkb_channel);
+  g_object_unref (kbd_channel);
 
+
   xfconf_shutdown();
 
   return EXIT_SUCCESS;

Modified: xfce4-settings/trunk/dialogs/mouse-settings/Makefile.am
===================================================================
--- xfce4-settings/trunk/dialogs/mouse-settings/Makefile.am	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/dialogs/mouse-settings/Makefile.am	2008-07-13 15:14:04 UTC (rev 27274)
@@ -1,7 +1,7 @@
 bin_PROGRAMS = xfce4-mouse-settings 
 xfce4_mouse_settings_SOURCES = \
 	main.c \
-	mouse-dialog_glade.h
+	mouse-dialog-glade.h
 
 xfce4_mouse_settings_CFLAGS = \
 	$(GTK_CFLAGS) \
@@ -10,6 +10,10 @@
 	$(DBUS_GLIB_CFLAGS) \
 	$(LIBXFCEGUI4_CFLAGS) \
 	$(XFCONF_CFLAGS) \
+	$(XI_CFLAGS) \
+	$(XCURSOR_CFLAGS) \
+	$(HAL_CFLAGS) \
+	$(XFCONF_CFLAGS) \
 	-DDATADIR=\"$(datadir)\" \
 	-DSRCDIR=\"$(top_srcdir)\" \
 	-DLOCALEDIR=\"$(localedir)\"
@@ -20,7 +24,10 @@
 	$(GLADE_LIBS) \
 	$(DBUS_GLIB_LIBS) \
 	$(LIBXFCEGUI4_LIBS) \
-	$(XFCONF_LIBS)
+	$(XFCONF_LIBS) \
+	$(HAL_LIBS) \
+	$(XI_LIBS) \
+	$(XCURSOR_LIBS)
 
 INCLUDES = \
 	-I${top_srcdir} \
@@ -29,9 +36,9 @@
 if MAINTAINER_MODE
 
 BUILT_SOURCES = \
-mouse-dialog_glade.h
+mouse-dialog-glade.h
 
-mouse-dialog_glade.h: mouse-dialog.glade
+mouse-dialog-glade.h: mouse-dialog.glade
 	exo-csource --static --name=mouse_dialog_glade $< >$@
 
 endif

Modified: xfce4-settings/trunk/dialogs/mouse-settings/main.c
===================================================================
--- xfce4-settings/trunk/dialogs/mouse-settings/main.c	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/dialogs/mouse-settings/main.c	2008-07-13 15:14:04 UTC (rev 27274)
@@ -1,7 +1,5 @@
 /*
- *  Copyright (c) 2008 Stephan Arts <stephan at xfce.org>
  *  Copyright (c) 2008 Nick Schermer <nick at xfce.org>
- *  Copyright (c) 2008 Mike Massonnet <mmassonnet at xfce.org>
  *
  *  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
@@ -36,38 +34,61 @@
 #endif
 
 #include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#ifdef HAVE_XCURSOR
 #include <X11/Xcursor/Xcursor.h>
+#endif /* !HAVE_XCURSOR */
 
+#ifdef HAVE_HAL
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <hal/libhal.h>
+#endif /* !HAVE_HAL */
+
 #include <gtk/gtk.h>
+#include <gdk/gdkx.h>
 #include <glade/glade.h>
+
 #include <xfconf/xfconf.h>
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
-#include "mouse-dialog_glade.h"
+#include "mouse-dialog-glade.h"
 
 
+
 /* settings */
+#ifdef HAVE_XCURSOR
 #define PREVIEW_ROWS    (3)
 #define PREVIEW_COLUMNS (6)
 #define PREVIEW_SIZE    (24)
 #define PREVIEW_SPACING (2)
+#endif /* !HAVE_XCURSOR */
 
 
+/* global setting channels */
+XfconfChannel *xsettings_channel;
+XfconfChannel *xdevices_channel;
 
-/* treeview columns */
-enum
+/* lock counter to avoid signals during updates */
+static gint locked = 0;
+
+/* the display for this window */
+static GdkDisplay *display;
+
+/* device update id */
+static guint timeout_id = 0;
+
+/* option entries */
+static gboolean opt_version = FALSE;
+
+static GOptionEntry option_entries[] =
 {
-    COLUMN_THEME_PIXBUF,
-    COLUMN_THEME_PATH,
-    COLUMN_THEME_NAME,
-    COLUMN_THEME_REAL_NAME,
-    COLUMN_THEME_COMMENT,
-    N_THEME_COLUMNS
+    { "version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL },
+    { NULL }
 };
 
-
-
+#ifdef HAVE_XCURSOR
 /* icon names for the preview widget */
 static const gchar *preview_names[] = {
     "left_ptr",            "left_ptr_watch",    "watch",             "hand2",
@@ -81,22 +102,29 @@
     "top_side",            "top_tee"
 };
 
+enum
+{
+    COLUMN_THEME_PIXBUF,
+    COLUMN_THEME_PATH,
+    COLUMN_THEME_NAME,
+    COLUMN_THEME_DISPLAY_NAME,
+    COLUMN_THEME_COMMENT,
+    N_THEME_COLUMNS
+};
+#endif /* !HAVE_XCURSOR */
 
-
-/* option entries */
-static gboolean opt_version = FALSE;
-
-static GOptionEntry option_entries[] =
+enum
 {
-    { "version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL },
-    { NULL }
+    COLUMN_DEVICE_ICON,
+    COLUMN_DEVICE_NAME,
+    COLUMN_DEVICE_DISPLAY_NAME,
+    COLUMN_DEVICE_XID,
+    COLUMN_DEVICE_NBUTTONS,
+    N_DEVICE_COLUMNS
 };
 
-/* global xfconf channel */
-static XfconfChannel *xsettings_channel;
 
-
-
+#ifdef HAVE_XCURSOR
 static GdkPixbuf *
 mouse_settings_themes_pixbuf_from_filename (const gchar *filename,
                                             guint        size)
@@ -194,7 +222,7 @@
 
 static void
 mouse_settings_themes_preview_image (const gchar *path,
-                                     GtkWidget   *image)
+                                     GtkImage    *image)
 {
     GdkPixbuf *pixbuf;
     GdkPixbuf *preview;
@@ -257,26 +285,100 @@
 
 
 
-static GtkTreePath *
-mouse_settings_themes_populate_store (GtkListStore *store)
+static void
+mouse_settings_themes_selection_changed (GtkTreeSelection *selection,
+                                         GladeXML       *gxml)
 {
-    const gchar  *path;
-    gchar       **basedirs;
-    gint          i;
-    gchar        *homedir;
-    GDir         *dir;
-    const gchar  *theme;
-    gchar        *filename;
-    gchar        *index_file;
-    XfceRc       *rc;
-    const gchar  *name;
-    const gchar  *comment;
+    GtkTreeModel *model;
     GtkTreeIter   iter;
-    gint          position = 0;
-    GdkPixbuf    *pixbuf;
-    gchar        *active_theme;
-    GtkTreePath  *active_path = NULL;
+    gboolean      has_selection;
+    gchar        *path, *name;
+    GtkWidget      *image;
 
+    has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
+    if (G_LIKELY (has_selection))
+    {
+        /* get theme information from model */
+        gtk_tree_model_get (model, &iter, COLUMN_THEME_PATH, &path,
+                            COLUMN_THEME_NAME, &name, -1);
+
+        /* update the preview widget */
+        image = glade_xml_get_widget (gxml, "mouse-theme-preview");
+        mouse_settings_themes_preview_image (path, GTK_IMAGE (image));
+
+        /* write configuration (not during a lock) */
+        if (locked == 0)
+            xfconf_channel_set_string (xsettings_channel, "/Gtk/CursorThemeName", name);
+
+        /* cleanup */
+        g_free (path);
+        g_free (name);
+    }
+}
+
+
+
+static gint
+mouse_settings_themes_sort_func (GtkTreeModel *model,
+                                 GtkTreeIter  *a,
+                                 GtkTreeIter  *b,
+                                 gpointer      user_data)
+{
+    gchar *name_a, *name_b;
+    gint   retval;
+
+    /* get the names from the model */
+    gtk_tree_model_get (model, a, COLUMN_THEME_DISPLAY_NAME, &name_a, -1);
+    gtk_tree_model_get (model, b, COLUMN_THEME_DISPLAY_NAME, &name_b, -1);
+
+    /* make sure the names are not null */
+    if (G_UNLIKELY (name_a == NULL))
+        name_a = g_strdup ("");
+    if (G_UNLIKELY (name_b == NULL))
+        name_b = g_strdup ("");
+
+    /* sort the names but keep Default on top */
+    if (g_utf8_collate (name_a, _("Default")) == 0)
+        retval = -1;
+    else if (g_utf8_collate (name_b, _("Default")) == 0)
+        retval = 1;
+    else
+        retval = g_utf8_collate (name_a, name_b);
+
+    /* cleanup */
+    g_free (name_a);
+    g_free (name_b);
+
+    return retval;
+}
+
+
+
+static void
+mouse_settings_themes_populate_store (GladeXML *gxml)
+{
+    const gchar        *path;
+    gchar             **basedirs;
+    gint                i;
+    gchar              *homedir;
+    GDir               *dir;
+    const gchar        *theme;
+    gchar              *filename;
+    gchar              *index_file;
+    XfceRc             *rc;
+    const gchar        *name;
+    const gchar        *comment;
+    GtkTreeIter         iter;
+    gint                position = 0;
+    GdkPixbuf          *pixbuf;
+    gchar              *active_theme;
+    GtkTreePath        *active_path = NULL;
+    GtkListStore       *store;
+    GtkCellRenderer    *renderer;
+    GtkTreeViewColumn  *column;
+    GtkWidget          *treeview;
+    GtkTreeSelection   *selection;
+
     /* get the cursor paths */
 #if XCURSOR_LIB_MAJOR == 1 && XCURSOR_LIB_MINOR < 1
     path = "~/.icons:/usr/share/icons:/usr/share/pixmaps:/usr/X11R6/lib/X11/icons";
@@ -289,15 +391,18 @@
 
     /* get the active theme */
     active_theme = xfconf_channel_get_string (xsettings_channel, "/Gtk/CursorThemeName", "default");
-    
+
+    /* create the store */
+    store = gtk_list_store_new (N_THEME_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING,
+                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+
     /* insert default */
     gtk_list_store_insert_with_values (store, &iter, position++,
                                        COLUMN_THEME_NAME, "default",
-                                       COLUMN_THEME_REAL_NAME, _("Default"), -1);
+                                       COLUMN_THEME_DISPLAY_NAME, _("Default"), -1);
 
-    /* check if the users uses the default theme */
-    if (strcmp (active_theme, "default") == 0)
-        active_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+    /* store the default path, so we always select a theme */
+    active_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
 
     if (G_LIKELY (basedirs))
     {
@@ -337,12 +442,15 @@
                         gtk_list_store_insert_with_values (store, &iter, position++,
                                                            COLUMN_THEME_PIXBUF, pixbuf,
                                                            COLUMN_THEME_NAME, theme,
-                                                           COLUMN_THEME_REAL_NAME, theme,
+                                                           COLUMN_THEME_DISPLAY_NAME, theme,
                                                            COLUMN_THEME_PATH, filename, -1);
 
                         /* check if this is the active theme, set the path */
-                        if (strcmp (active_theme, theme) == 0 && active_path == NULL)
+                        if (strcmp (active_theme, theme) == 0)
+                        {
+                            gtk_tree_path_free (active_path);
                             active_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+                        }
 
                         /* release pixbuf */
                         if (G_LIKELY (pixbuf))
@@ -368,7 +476,7 @@
 
                                     /* update store */
                                     gtk_list_store_set (store, &iter,
-                                                        COLUMN_THEME_REAL_NAME, name,
+                                                        COLUMN_THEME_DISPLAY_NAME, name,
                                                         COLUMN_THEME_COMMENT, comment, -1);
                                 }
 
@@ -400,165 +508,553 @@
     /* cleanup */
     g_free (active_theme);
 
-    return active_path;
+    /* set the treeview store */
+    treeview = glade_xml_get_widget (gxml, "mouse-theme-treeview");
+    gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
+#if GTK_CHECK_VERSION (2, 12, 0)
+    gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), COLUMN_THEME_COMMENT);
+#endif
+
+    /* setup the columns */
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    column = gtk_tree_view_column_new_with_attributes ("", renderer, "pixbuf", COLUMN_THEME_PIXBUF, NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+    renderer = gtk_cell_renderer_text_new ();
+    column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", COLUMN_THEME_DISPLAY_NAME, NULL);
+    g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+    /* setup selection */
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+    gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+    g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (mouse_settings_themes_selection_changed), gxml);
+
+    /* select the active theme in the treeview */
+    gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), active_path, NULL, FALSE);
+    gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (treeview), active_path, NULL, FALSE, 0.5, 0.0);
+    gtk_tree_path_free (active_path);
+
+    /* sort the store */
+    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), COLUMN_THEME_DISPLAY_NAME, mouse_settings_themes_sort_func, NULL, NULL);
+    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), COLUMN_THEME_DISPLAY_NAME, GTK_SORT_ASCENDING);
+
+    /* release the store */
+    g_object_unref (G_OBJECT (store));
 }
+#endif /* !HAVE_XCURSOR */
 
 
 
 static void
-mouse_settings_themes_selection_changed (GtkTreeSelection *selection,
+mouse_settings_device_selection_changed (GtkTreeSelection *selection,
                                          GladeXML         *gxml)
 {
-    GtkTreeModel *model;
-    GtkTreeIter   iter;
-    gboolean      has_selection;
-    gchar        *path, *name;
+    gint               nbuttons;
+    Display           *xdisplay;
+    XDevice           *device;
+    XFeedbackState    *states;
+    gint               nstates;
+    XPtrFeedbackState *state;
+    gint               i;
+    guchar            *buttonmap;
+    gint               id_1 = 0, id_3 = 0;
+    gint               id_4 = 0, id_5 = 0;
+    gdouble            acceleration = -1.00;
+    gint               threshold = -1;
+    GtkWidget         *widget;
+    GtkTreeModel      *model;
+    GtkTreeIter        iter;
+    gboolean           has_selection;
+    XID                xid;
 
+    /* lock the dialog */
+    locked++;
+
+    /* get the selected item */
     has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
     if (G_LIKELY (has_selection))
     {
-        /* get theme information from model */
-        gtk_tree_model_get (model, &iter, COLUMN_THEME_PATH, &path,
-                            COLUMN_THEME_NAME, &name, -1);
+        /* get device id and number of buttons */
+        gtk_tree_model_get (model, &iter, COLUMN_DEVICE_XID, &xid,
+                            COLUMN_DEVICE_NBUTTONS, &nbuttons, -1);
 
-        /* update the preview widget */
-        mouse_settings_themes_preview_image (path, glade_xml_get_widget (gxml, "cursor_preview_image"));
+        /* get the x display */
+        xdisplay = gdk_x11_display_get_xdisplay (display);
 
-        /* write configuration */
-        xfconf_channel_set_string (xsettings_channel, "/Gtk/CursorThemeName", name);
+        /* open the device */
+        device = XOpenDevice (xdisplay, xid);
 
-        /* cleanup */
-        g_free (path);
-        g_free (name);
+        if (G_LIKELY (device))
+        {
+            /* allocate button map */
+            buttonmap = g_new0 (guchar, nbuttons);
+
+            /* get the button mapping */
+            XGetDeviceButtonMapping (xdisplay, device, buttonmap, nbuttons);
+
+            /* figure out the position of the first and second/third button in the map */
+            for (i = 0; i < nbuttons; i++)
+            {
+                if (buttonmap[i] == 1)
+                    id_1 = i;
+                else if (buttonmap[i] == (nbuttons < 3 ? 2 : 3))
+                    id_3 = i;
+                else if (buttonmap[i] == 4)
+                    id_4 = i;
+                else if (buttonmap[i] == 5)
+                    id_5 = i;
+            }
+
+            /* cleanup */
+            g_free (buttonmap);
+
+            /* get the feedback states for this device */
+            states = XGetFeedbackControl (xdisplay, device, &nstates);
+
+            /* intial values */
+            acceleration = threshold = -1;
+
+            /* get the pointer feedback class */
+            for (i = 0; i < nstates; i++)
+            {
+                if (states->class == PtrFeedbackClass)
+                {
+                    /* get the state */
+                    state = (XPtrFeedbackState *) states;
+
+                    /* set values */
+                    acceleration = (gdouble) state->accelNum / (gdouble) state->accelDenom;
+                    threshold = state->threshold;
+
+                    /* done */
+                    break;
+                }
+
+                /* advance the offset */
+                states = (XFeedbackState *) ((gchar *) states + states->length);
+            }
+
+            /* close the device */
+            XCloseDevice (xdisplay, device);
+        }
     }
+
+    /* update button order */
+    widget = glade_xml_get_widget (gxml, id_1 > id_3 ? "mouse-left-handed" : "mouse-right-handed");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
+
+    widget = glade_xml_get_widget (gxml, "mouse-reverse-scrolling");
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), !!(id_5 < id_4));
+    gtk_widget_set_sensitive (widget, nbuttons >= 5);
+
+    /* update acceleration scale */
+    widget = glade_xml_get_widget (gxml, "mouse-acceleration-scale");
+    gtk_range_set_value (GTK_RANGE (widget), acceleration);
+    gtk_widget_set_sensitive (GTK_WIDGET (widget), acceleration != -1);
+
+    /* update threshold scale */
+    widget = glade_xml_get_widget (gxml, "mouse-threshold-scale");
+    gtk_range_set_value (GTK_RANGE (widget), threshold);
+    gtk_widget_set_sensitive (GTK_WIDGET (widget), threshold != -1);
+
+    /* unlock */
+    locked--;
 }
 
 
 
-static gint
-mouse_settings_themes_sort_func (GtkTreeModel *model,
-                                 GtkTreeIter  *a,
-                                 GtkTreeIter  *b,
-                                 gpointer      user_data)
+static void
+mouse_settings_device_save (GladeXML *gxml)
 {
-    gchar *name_a, *name_b;
-    gint   retval;
-    
-    /* get the names from the model */
-    gtk_tree_model_get (model, a, COLUMN_THEME_REAL_NAME, &name_a, -1);
-    gtk_tree_model_get (model, b, COLUMN_THEME_REAL_NAME, &name_b, -1);
-    
-    /* make sure the names are not null */
-    if (G_UNLIKELY (name_a == NULL))
-        name_a = g_strdup ("");
-    if (G_UNLIKELY (name_b == NULL))
-        name_b = g_strdup ("");
-    
-    /* sort the names but keep Default on top */
-    if (g_utf8_collate (name_a, _("Default")) == 0)
-        retval = -1;
-    else if (g_utf8_collate (name_b, _("Default")) == 0)
-        retval = 1;
-    else
-        retval = g_utf8_collate (name_a, name_b);
-    
-    /* cleanup */
-    g_free (name_a);
-    g_free (name_b);
-    
-    return retval;
+    GtkWidget        *treeview;
+    GtkTreeSelection *selection;
+    GtkTreeModel     *model;
+    GtkTreeIter       iter;
+    gboolean          has_selection;
+    gchar            *name;
+    GtkWidget        *widget;
+    gchar            *property_name;
+    gboolean          righthanded;
+    gint              threshold;
+    gdouble           acceleration;
+    gboolean          reverse_scrolling;
+
+    g_return_if_fail (GLADE_IS_XML (gxml));
+
+    /* leave when locked */
+    if (locked > 0)
+        return;
+
+    /* get the treeview */
+    treeview = glade_xml_get_widget (gxml, "mouse-devices-treeview");
+
+    /* get the selection */
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+    has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
+    if (G_LIKELY (has_selection))
+    {
+        /* get device id and number of buttons */
+        gtk_tree_model_get (model, &iter, COLUMN_DEVICE_NAME, &name, -1);
+
+        if (G_LIKELY (name))
+        {
+            /* store the button order */
+            widget = glade_xml_get_widget (gxml, "mouse-right-handed");
+            property_name = g_strdup_printf ("/Pointers/%s/RightHanded", name);
+            righthanded = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+            if (xfconf_channel_get_bool (xdevices_channel, property_name, TRUE) != righthanded)
+                xfconf_channel_set_bool (xdevices_channel, property_name, righthanded);
+            g_free (property_name);
+
+            /* store reverse scrolling */
+            widget = glade_xml_get_widget (gxml, "mouse-reverse-scrolling");
+            property_name = g_strdup_printf ("/Pointers/%s/ReverseScrolling", name);
+            reverse_scrolling = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+            if (xfconf_channel_get_bool (xdevices_channel, property_name, TRUE) != reverse_scrolling)
+                xfconf_channel_set_bool (xdevices_channel, property_name, reverse_scrolling);
+            g_free (property_name);
+
+            /* store the threshold */
+            widget = glade_xml_get_widget (gxml, "mouse-threshold-scale");
+            property_name = g_strdup_printf ("/Pointers/%s/Threshold", name);
+            threshold = gtk_range_get_value (GTK_RANGE (widget));
+            if (xfconf_channel_get_int (xdevices_channel, property_name, -1) != threshold)
+                xfconf_channel_set_int (xdevices_channel, property_name, threshold);
+            g_free (property_name);
+
+            /* store the acceleration */
+            widget = glade_xml_get_widget (gxml, "mouse-acceleration-scale");
+            property_name = g_strdup_printf ("/Pointers/%s/Acceleration", name);
+            acceleration = gtk_range_get_value (GTK_RANGE (widget));
+            if (xfconf_channel_get_double (xdevices_channel, property_name, -1) != acceleration)
+                xfconf_channel_set_double (xdevices_channel, property_name, acceleration);
+            g_free (property_name);
+
+            /* cleanup */
+            g_free (name);
+        }
+    }
 }
 
 
 
-static GtkWidget *
-mouse_settings_dialog_new_from_xml (GladeXML *gxml)
+static gchar *
+mouse_settings_device_xfconf_name (const gchar *name)
 {
+    GString     *string;
+    const gchar *p;
+
+    /* NOTE: this function exists in both the dialog and
+     *       helper code and they have to identical! */
+
+    /* allocate a string */
+    string = g_string_sized_new (strlen (name));
+
+    /* create a name with only valid chars */
+    for (p = name; *p != '\0'; p++)
+    {
+        if ((*p >= 'A' && *p <= 'Z')
+            || (*p >= 'a' && *p <= 'z')
+            || (*p >= '0' && *p <= '9')
+            || *p == '_' || *p == '-')
+          string = g_string_append_c (string, *p);
+        else if (*p == ' ')
+            string = g_string_append_c (string, '_');
+    }
+
+    /* return the new string */
+    return g_string_free (string, FALSE);
+}
+
+
+
+static void
+mouse_settings_device_populate_store (GladeXML *gxml,
+                                      gboolean  create_store)
+{
+    Display           *xdisplay;
+    XDeviceInfo       *device_list, *device_info;
+    gchar             *display_name, *usb;
+    gshort             num_buttons;
+    gint               ndevices;
+    gint               i, m;
+    XAnyClassPtr       ptr;
+    GtkTreeIter        iter;
     GtkListStore      *store;
     GtkWidget         *treeview;
+    GtkTreePath       *path;
     GtkTreeViewColumn *column;
     GtkCellRenderer   *renderer;
     GtkTreeSelection  *selection;
-    GtkWidget         *widget;
-    GtkTreePath       *path;
-    GtkWidget         *dialog;
-    GtkAdjustment     *adjustment;
+    gchar             *device_name;
 
-    /* setup the icon theme treeview */
-    store = gtk_list_store_new (N_THEME_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    /* lock */
+    locked++;
 
-    /* add all the themes to the tree */
-    path = mouse_settings_themes_populate_store (store);
+    /* get the treeview */
+    treeview = glade_xml_get_widget (gxml, "mouse-devices-treeview");
 
-    treeview = glade_xml_get_widget (gxml, "treeview_cursor_theme");
-    gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
-#if GTK_CHECK_VERSION (2, 12, 0)
-    gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (treeview), COLUMN_THEME_COMMENT);
-#endif
+    /* create or get the store */
+    if (G_LIKELY (create_store))
+    {
+        store = gtk_list_store_new (N_DEVICE_COLUMNS, G_TYPE_STRING, G_TYPE_STRING,
+                                    G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
+    }
+    else
+    {
+        store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)));
+        gtk_list_store_clear (store);
+    }
 
-    g_object_unref (G_OBJECT (store));
+    /* get the x display */
+    xdisplay = gdk_x11_display_get_xdisplay (display);
 
-    renderer = gtk_cell_renderer_pixbuf_new ();
-    column = gtk_tree_view_column_new_with_attributes ("", renderer, "pixbuf", COLUMN_THEME_PIXBUF, NULL);
-    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+    /* get all the registered devices */
+    device_list = XListInputDevices (xdisplay, &ndevices);
 
-    renderer = gtk_cell_renderer_text_new ();
-    column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", COLUMN_THEME_REAL_NAME, NULL);
-    g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+    for (i = 0; i < ndevices; i++)
+    {
+        /* get the device */
+        device_info = &device_list[i];
 
+        /* filter out the pointer devices */
+        if (device_info->use == IsXExtensionPointer)
+        {
+            /* get the device name */
+            display_name = g_strdup (device_info->name);
+
+            /* get rid of usb crap in the name */
+            if ((usb = strstr (display_name, "-usb")) != NULL)
+                *usb = '\0';
+
+            /* get the device classes */
+            ptr = device_info->inputclassinfo;
+
+            /* walk all the classes */
+            for (m = 0, num_buttons = 0; m < device_info->num_classes; m++)
+            {
+                /* find the button class */
+                if (ptr->class == ButtonClass)
+                {
+                    /* get the number of buttons */
+                    num_buttons = ((XButtonInfoPtr) ptr)->num_buttons;
+
+                    /* done */
+                    break;
+                }
+
+                /* advance the offset */
+                ptr = (XAnyClassPtr) ((gchar *) ptr + ptr->length);
+            }
+
+            /* insert the device if it has buttons */
+            if (G_LIKELY (num_buttons > 0))
+            {
+                /* create a valid xfconf device name */
+                device_name = mouse_settings_device_xfconf_name (device_info->name);
+
+                /* insert in the store */
+                gtk_list_store_insert_with_values (store, &iter, i,
+                                                   COLUMN_DEVICE_ICON, "input-mouse",
+                                                   COLUMN_DEVICE_NAME, device_name,
+                                                   COLUMN_DEVICE_DISPLAY_NAME, display_name,
+                                                   COLUMN_DEVICE_XID, device_info->id,
+                                                   COLUMN_DEVICE_NBUTTONS, num_buttons, -1);
+
+                /* cleanup */
+                g_free (device_name);
+            }
+
+            /* cleanup */
+            g_free (display_name);
+        }
+    }
+
+    /* cleanup */
+    XFreeDeviceList (device_list);
+
+    /* get the selection */
     selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
-    gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-    g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (mouse_settings_themes_selection_changed), gxml);
 
-    /* select the active item */
-    if (G_LIKELY (path != NULL))
+    if (G_LIKELY (create_store))
     {
-        gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, NULL, FALSE);
-        gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (treeview), path, NULL, FALSE, 0.5, 0.0);
-        gtk_tree_path_free (path);
+        /* set the treeview model */
+        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
+        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), COLUMN_DEVICE_XID, GTK_SORT_ASCENDING);
+        g_object_unref (G_OBJECT (store));
+
+        /* icon renderer */
+        renderer = gtk_cell_renderer_pixbuf_new ();
+        column = gtk_tree_view_column_new_with_attributes ("", renderer, "icon-name", COLUMN_DEVICE_ICON, NULL);
+        g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DND, NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        /* text renderer */
+        renderer = gtk_cell_renderer_text_new ();
+        column = gtk_tree_view_column_new_with_attributes ("", renderer, "text", COLUMN_DEVICE_DISPLAY_NAME, NULL);
+        g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+        /* setup tree selection */
+        gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+        g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (mouse_settings_device_selection_changed), gxml);
     }
 
-    /* sort the tree, after setting the active item */
-    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), COLUMN_THEME_REAL_NAME,
-                                     mouse_settings_themes_sort_func, NULL, NULL);
-    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), COLUMN_THEME_REAL_NAME, 
-                                          GTK_SORT_ASCENDING);
+    /* select the first mouse in the tree */
+    path = gtk_tree_path_new_first ();
+    gtk_tree_selection_select_path (selection, path);
+    gtk_tree_path_free (path);
 
-    /* connect xfconf properties */
-    widget = glade_xml_get_widget (gxml, "button_right_handed");
-    xfconf_g_property_bind(xsettings_channel, "/Mouse/RightHanded", G_TYPE_INT, G_OBJECT (widget), "active");
+    /* unlock */
+    locked--;
+}
 
-    adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse_motion_acceleration")));
-    xfconf_g_property_bind(xsettings_channel, "/Mouse/Acceleration", G_TYPE_INT, G_OBJECT (adjustment), "value");
 
-    adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse_motion_threshold")));
-    xfconf_g_property_bind(xsettings_channel, "/Mouse/Threshold", G_TYPE_INT, G_OBJECT (adjustment), "value");
 
-    adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse_dnd_threshold")));
-    xfconf_g_property_bind(xsettings_channel, "/Net/DndDragThreshold", G_TYPE_INT, G_OBJECT (adjustment), "value");
+static gboolean
+mouse_settings_device_update_sliders (gpointer user_data)
+{
+    GladeXML  *gxml = GLADE_XML (user_data);
+    GtkWidget *treeview;
+    GtkWidget *button;
 
-    adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse_double_click_speed")));
-    xfconf_g_property_bind(xsettings_channel, "/Net/DoubleClickTime", G_TYPE_INT, G_OBJECT (adjustment), "value");
+    GDK_THREADS_ENTER ();
 
-    widget = glade_xml_get_widget (gxml, "spin_cursor_size");
-    xfconf_g_property_bind (xsettings_channel, "/Gtk/CursorThemeSize", G_TYPE_INT, G_OBJECT (widget), "value");
+    /* get the treeview */
+    treeview = glade_xml_get_widget (gxml, "mouse-devices-treeview");
 
-    /* show all the dialog widgets */
-    dialog = glade_xml_get_widget (gxml, "mouse-settings-dialog");
-    gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
+    /* update */
+    mouse_settings_device_selection_changed (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), gxml);
 
-    return dialog;
+    /* make the button sensitive again */
+    button = glade_xml_get_widget (gxml, "mouse-reset");
+    gtk_widget_set_sensitive (button, TRUE);
+
+    GDK_THREADS_LEAVE ();
+
+    return FALSE;
 }
 
 
 
+static void
+mouse_settings_device_list_changed_timeout_destroyed (gpointer user_data)
+{
+    /* reset the timeout id */
+    timeout_id = 0;
+}
+
+
+
+#ifdef HAVE_HAL
+static gboolean
+mouse_settings_device_list_changed_timeout (gpointer user_data)
+{
+    GladeXML *gxml = GLADE_XML (user_data);
+
+    GDK_THREADS_ENTER ();
+
+    /* update the list */
+    mouse_settings_device_populate_store (gxml, FALSE);
+
+    GDK_THREADS_LEAVE ();
+
+    return FALSE;
+}
+
+
+
+static void
+mouse_settings_device_list_changed (LibHalContext *context,
+                                    const gchar   *udi)
+{
+    GladeXML *gxml;
+
+    /* queue a new timeout if none is set */
+    if (timeout_id == 0)
+    {
+        /* get the user data */
+        gxml = libhal_ctx_get_user_data (context);
+
+        /* update the dialog in 1 second */
+        timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 1000, mouse_settings_device_list_changed_timeout,
+                                         gxml, mouse_settings_device_list_changed_timeout_destroyed);
+    }
+}
+#endif  /* !HAVE_HAL */
+
+
+static void
+mouse_settings_device_reset (GtkWidget *button,
+                             GladeXML  *gxml)
+{
+    GtkWidget        *treeview;
+    GtkTreeSelection *selection;
+    gchar            *name, *property_name;
+    gboolean          has_selection;
+    GtkTreeModel     *model;
+    GtkTreeIter       iter;
+
+    /* leave when locked */
+    if (locked > 0)
+        return;
+
+    /* get the treeview */
+    treeview = glade_xml_get_widget (gxml, "mouse-devices-treeview");
+
+    /* get the selection */
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+    has_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
+    if (G_LIKELY (has_selection))
+    {
+        /* get device id and number of buttons */
+        gtk_tree_model_get (model, &iter, COLUMN_DEVICE_NAME, &name, -1);
+
+        if (G_LIKELY (name && timeout_id == 0))
+        {
+            /* make the button insensitive */
+            gtk_widget_set_sensitive (button, FALSE);
+
+            /* set the threshold to -1 */
+            property_name = g_strdup_printf ("/Pointers/%s/Threshold", name);
+            xfconf_channel_set_int (xdevices_channel, property_name, -1);
+            g_free (property_name);
+
+            /* set the acceleration to -1 */
+            property_name = g_strdup_printf ("/Pointers/%s/Acceleration", name);
+            xfconf_channel_set_double (xdevices_channel, property_name, -1.00);
+            g_free (property_name);
+
+            /* update the sliders in 500ms */
+            timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 500, mouse_settings_device_update_sliders,
+                                             gxml, mouse_settings_device_list_changed_timeout_destroyed);
+
+
+        }
+
+        /* cleanup */
+        g_free (name);
+    }
+}
+
+
+
 gint
 main(gint argc, gchar **argv)
 {
-    GtkWidget *dialog;
-    GladeXML  *gxml;
-    GError    *error = NULL;
+    GtkWidget      *dialog;
+    GladeXML       *gxml;
+    GError         *error = NULL;
+    GtkAdjustment  *adjustment;
+    GtkWidget      *widget;
+#ifdef HAVE_HAL
+    DBusConnection *connection;
+    LibHalContext  *context = NULL;
+    DBusError       derror;
+#endif /* !HAVE_HAL */
 
     /* setup translation domain */
     xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
@@ -595,31 +1091,161 @@
     }
 
     /* initialize xfconf */
-    xfconf_init (NULL);
+    if (G_UNLIKELY (!xfconf_init (&error)))
+    {
+        /* print error and leave */
+        g_critical ("Failed to connect to Xfconf daemon: %s", error->message);
+        g_error_free (error);
+        
+        return EXIT_FAILURE;
+    }
 
-    /* open the xsettings channel */
+    /* open the xsettings and xdevices channel */
     xsettings_channel = xfconf_channel_new ("xsettings");
-    if (G_LIKELY (xsettings_channel))
+    xdevices_channel = xfconf_channel_new ("xdevices");
+
+    if (G_LIKELY (xdevices_channel && xsettings_channel))
     {
-        /* load the dialog glade xml */
+        /* load the glade xml file */
         gxml = glade_xml_new_from_buffer (mouse_dialog_glade, mouse_dialog_glade_length, NULL, NULL);
         if (G_LIKELY (gxml))
         {
-            /* build the dialog */
-            dialog = mouse_settings_dialog_new_from_xml (gxml);
+            /* lock */
+            locked++;
 
-            /* run the dialog */
+            /* set the working display for this instance */
+            display = gdk_display_get_default ();
+
+            /* populate the devices treeview */
+            mouse_settings_device_populate_store (gxml, TRUE);
+
+            /* connect signals */
+            widget = glade_xml_get_widget (gxml, "mouse-acceleration-scale");
+            g_signal_connect_swapped (G_OBJECT (widget), "value-changed", G_CALLBACK (mouse_settings_device_save), gxml);
+
+            widget = glade_xml_get_widget (gxml, "mouse-threshold-scale");
+            g_signal_connect_swapped (G_OBJECT (widget), "value-changed", G_CALLBACK (mouse_settings_device_save), gxml);
+
+            widget = glade_xml_get_widget (gxml, "mouse-left-handed");
+            g_signal_connect_swapped (G_OBJECT (widget), "toggled", G_CALLBACK (mouse_settings_device_save), gxml);
+
+            widget = glade_xml_get_widget (gxml, "mouse-right-handed");
+            g_signal_connect_swapped (G_OBJECT (widget), "toggled", G_CALLBACK (mouse_settings_device_save), gxml);
+
+            widget = glade_xml_get_widget (gxml, "mouse-reverse-scrolling");
+            g_signal_connect_swapped (G_OBJECT (widget), "toggled", G_CALLBACK (mouse_settings_device_save), gxml);
+
+            widget = glade_xml_get_widget (gxml, "mouse-reset");
+            g_signal_connect (G_OBJECT (widget), "clicked", G_CALLBACK (mouse_settings_device_reset), gxml);
+
+#ifdef HAVE_XCURSOR
+            /* populate the themes treeview */
+            mouse_settings_themes_populate_store (gxml);
+
+            /* connect the cursor size in the cursor tab */
+            widget = glade_xml_get_widget (gxml, "mouse-cursor-size");
+            xfconf_g_property_bind (xsettings_channel, "/Gtk/CursorThemeSize", G_TYPE_INT, G_OBJECT (widget), "value");
+#else
+            /* hide the themes tab */
+            widget = glade_xml_get_widget (gxml, "mouse-themes-hbox");
+            gtk_widget_hide (widget);
+#endif /* !HAVE_XCURSOR */
+
+            /* connect sliders in the gtk tab */
+            adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse-dnd-threshold")));
+            xfconf_g_property_bind (xsettings_channel, "/Net/DndDragThreshold", G_TYPE_INT, G_OBJECT (adjustment), "value");
+
+            adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse-double-click-time")));
+            xfconf_g_property_bind (xsettings_channel, "/Net/DoubleClickTime", G_TYPE_INT, G_OBJECT (adjustment), "value");
+
+            adjustment = gtk_range_get_adjustment (GTK_RANGE (glade_xml_get_widget (gxml, "mouse-double-click-distance")));
+            xfconf_g_property_bind (xsettings_channel, "/Net/DoubleClickDistance", G_TYPE_INT, G_OBJECT (adjustment), "value");
+
+#ifdef HAVE_HAL
+            /* initialize the dbus error variable */
+            dbus_error_init (&derror);
+
+            /* connect to the dbus system bus */
+            connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror);
+            if (G_LIKELY (connection))
+            {
+                /* connect dbus to the main loop */
+                dbus_connection_setup_with_g_main (connection, NULL);
+
+                /* create hal context */
+                context = libhal_ctx_new ();
+                if (G_LIKELY (context))
+                {
+                    /* set user data for the callbacks */
+                    libhal_ctx_set_user_data (context, gxml);
+
+                    /* set the dbus connection */
+                    if (G_LIKELY (libhal_ctx_set_dbus_connection (context, connection)))
+                    {
+                        /* connect to hal */
+                        if (G_LIKELY (libhal_ctx_init (context, &derror)))
+                        {
+                            /* add callbacks for device changes */
+                            libhal_ctx_set_device_added (context, mouse_settings_device_list_changed);
+                            libhal_ctx_set_device_removed (context, mouse_settings_device_list_changed);
+                        }
+                        else
+                        {
+                           /* print warning */
+                           g_warning ("Failed to connect to hald: %s", derror.message);
+
+                           /* cleanup */
+                           LIBHAL_FREE_DBUS_ERROR (&derror);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                /* print warning */
+                g_warning ("Failed to connect to DBus: %s", derror.message);
+
+                /* cleanup */
+                LIBHAL_FREE_DBUS_ERROR (&derror);
+            }
+#endif /* !HAVE_HAL */
+
+            /* gtk the dialog */
+            dialog = glade_xml_get_widget (gxml, "mouse-dialog");
+
+            /* unlock */
+            locked--;
+
+            /* show the dialog */
             gtk_dialog_run (GTK_DIALOG (dialog));
 
+#ifdef HAVE_HAL
+            /* close the hal connection */
+            if (G_LIKELY (context))
+            {
+                libhal_ctx_shutdown (context, NULL);
+                libhal_ctx_free (context);
+            }
+
+            /* close the dbus connection */
+            if (G_LIKELY (connection))
+                dbus_connection_unref (connection);
+
+            /* stop any running sources */
+            if (G_UNLIKELY (timeout_id != 0))
+                g_source_remove (timeout_id);
+#endif /* !HAVE_HAL */   
+
+            /* destroy the dialog */
+            gtk_widget_destroy (GTK_WIDGET (dialog));
+
             /* release the glade xml */
             g_object_unref (G_OBJECT (gxml));
-
-            /* destroy the dialog */
-            gtk_widget_destroy (dialog);
         }
 
-        /* release the channel */
+        /* release the channels */
         g_object_unref (G_OBJECT (xsettings_channel));
+        g_object_unref (G_OBJECT (xdevices_channel));
     }
 
     /* shutdown xfconf */
@@ -627,4 +1253,3 @@
 
     return EXIT_SUCCESS;
 }
-

Modified: xfce4-settings/trunk/dialogs/mouse-settings/mouse-dialog.glade
===================================================================
--- xfce4-settings/trunk/dialogs/mouse-settings/mouse-dialog.glade	2008-07-13 13:19:54 UTC (rev 27273)
+++ xfce4-settings/trunk/dialogs/mouse-settings/mouse-dialog.glade	2008-07-13 15:14:04 UTC (rev 27274)
@@ -1,70 +1,105 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Fri Jul 11 21:11:25 2008 -->
+<!--Generated with glade3 3.4.5 on Sat Jul 12 20:58:31 2008 -->
 <glade-interface>
   <requires lib="xfce4"/>
-  <widget class="XfceTitledDialog" id="mouse-settings-dialog">
-    <property name="title" translatable="yes">Xfce4 Mouse Settings</property>
+  <widget class="XfceTitledDialog" id="mouse-dialog">
+    <property name="title" translatable="yes">Xfce Mouse Settings</property>
     <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
-    <property name="default_width">400</property>
     <property name="icon_name">preferences-desktop-peripherals</property>
     <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
     <property name="has_separator">False</property>
+    <property name="subtitle" translatable="yes">Configure the look and feeling of the pointer devices</property>
     <child internal-child="vbox">
       <widget class="GtkVBox" id="dialog-vbox1">
         <property name="visible">True</property>
         <property name="spacing">2</property>
         <child>
-          <widget class="GtkVBox" id="vbox1">
+          <widget class="GtkNotebook" id="notebook1">
             <property name="visible">True</property>
+            <property name="can_focus">True</property>
             <property name="border_width">6</property>
-            <property name="spacing">6</property>
             <child>
-              <widget class="GtkNotebook" id="notebook1">
+              <widget class="GtkHBox" id="hbox1">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
+                <property name="border_width">6</property>
+                <property name="spacing">12</property>
                 <child>
-                  <widget class="GtkVBox" id="vbox2">
+                  <widget class="GtkScrolledWindow" id="scrolledwindow1">
                     <property name="visible">True</property>
-                    <property name="border_width">12</property>
-                    <property name="spacing">6</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="shadow_type">GTK_SHADOW_IN</property>
                     <child>
-                      <widget class="GtkFrame" id="frame_button_settings">
+                      <widget class="GtkTreeView" id="mouse-devices-treeview">
                         <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="headers_visible">False</property>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkVBox" id="vbox1">
+                    <property name="visible">True</property>
+                    <property name="spacing">12</property>
+                    <child>
+                      <widget class="GtkFrame" id="frame1">
+                        <property name="visible">True</property>
                         <property name="label_xalign">0</property>
                         <property name="shadow_type">GTK_SHADOW_NONE</property>
                         <child>
                           <widget class="GtkAlignment" id="alignment1">
                             <property name="visible">True</property>
-                            <property name="bottom_padding">6</property>
-                            <property name="left_padding">12</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <property name="right_padding">6</property>
                             <child>
-                              <widget class="GtkHBox" id="hbox1">
+                              <widget class="GtkVBox" id="vbox12">
                                 <property name="visible">True</property>
-                                <property name="border_width">6</property>
                                 <property name="spacing">12</property>
-                                <property name="homogeneous">True</property>
                                 <child>
-                                  <widget class="GtkRadioButton" id="button_left_handed">
+                                  <widget class="GtkVBox" id="vbox2">
                                     <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="label" translatable="yes">_Left handed</property>
-                                    <property name="use_underline">True</property>
-                                    <property name="response_id">0</property>
-                                    <property name="active">True</property>
-                                    <property name="draw_indicator">True</property>
+                                    <property name="spacing">2</property>
+                                    <child>
+                                      <widget class="GtkRadioButton" id="mouse-right-handed">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="label" translatable="yes">_Right handed</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="response_id">0</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                      </widget>
+                                    </child>
+                                    <child>
+                                      <widget class="GtkRadioButton" id="mouse-left-handed">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="label" translatable="yes">_Left handed</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="response_id">0</property>
+                                        <property name="active">True</property>
+                                        <property name="draw_indicator">True</property>
+                                        <property name="group">mouse-right-handed</property>
+                                      </widget>
+                                      <packing>
+                                        <property name="position">1</property>
+                                      </packing>
+                                    </child>
                                   </widget>
                                 </child>
                                 <child>
-                                  <widget class="GtkRadioButton" id="button_right_handed">
+                                  <widget class="GtkCheckButton" id="mouse-reverse-scrolling">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
-                                    <property name="label" translatable="yes">_Right handed</property>
+                                    <property name="tooltip" translatable="yes">When enabled, the scroll wheel will work in the opposite direction</property>
+                                    <property name="label" translatable="yes">Re_verse scroll direction</property>
                                     <property name="use_underline">True</property>
                                     <property name="response_id">0</property>
-                                    <property name="active">True</property>
                                     <property name="draw_indicator">True</property>
-                                    <property name="group">button_left_handed</property>
                                   </widget>
                                   <packing>
                                     <property name="position">1</property>
@@ -75,9 +110,9 @@
                           </widget>
                         </child>
                         <child>
-                          <widget class="GtkLabel" id="label3">
+                          <widget class="GtkLabel" id="label4">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;b&gt;Button Settings&lt;/b&gt;</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Button Order&lt;/b&gt;</property>
                             <property name="use_markup">True</property>
                           </widget>
                           <packing>
@@ -90,134 +125,99 @@
                       </packing>
                     </child>
                     <child>
-                      <widget class="GtkFrame" id="frame_motion_settings">
+                      <widget class="GtkFrame" id="frame2">
                         <property name="visible">True</property>
                         <property name="label_xalign">0</property>
                         <property name="shadow_type">GTK_SHADOW_NONE</property>
                         <child>
                           <widget class="GtkAlignment" id="alignment2">
                             <property name="visible">True</property>
-                            <property name="bottom_padding">6</property>
-                            <property name="left_padding">12</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <property name="right_padding">6</property>
                             <child>
-                              <widget class="GtkVBox" id="vbox4">
+                              <widget class="GtkVBox" id="vbox6">
                                 <property name="visible">True</property>
-                                <property name="border_width">6</property>
-                                <property name="spacing">6</property>
+                                <property name="spacing">12</property>
                                 <child>
-                                  <widget class="GtkLabel" id="label9">
+                                  <widget class="GtkVBox" id="vbox7">
                                     <property name="visible">True</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">_Acceleration:</property>
-                                    <property name="use_underline">True</property>
-                                    <property name="mnemonic_widget">mouse_motion_acceleration</property>
-                                  </widget>
-                                </child>
-                                <child>
-                                  <widget class="GtkHBox" id="hbox7">
-                                    <property name="visible">True</property>
                                     <property name="spacing">2</property>
                                     <child>
-                                      <widget class="GtkLabel" id="label23">
+                                      <widget class="GtkLabel" id="mouse-acceleration-label">
                                         <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Slow&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">_Acceleration:</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="mnemonic_widget">mouse-acceleration-scale</property>
                                       </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                      </packing>
                                     </child>
                                     <child>
-                                      <widget class="GtkHScale" id="mouse_motion_acceleration">
+                                      <widget class="GtkHScale" id="mouse-acceleration-scale">
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="tooltip" translatable="yes">The pointer will go 'acceleration' times as fast when it travels more than 'threshold' pixels in a short time</property>
-                                        <property name="adjustment">1 1 30 1 5 0</property>
-                                        <property name="digits">0</property>
-                                        <property name="draw_value">False</property>
+                                        <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                        <property name="adjustment">2 0.10000000000000001 10 0.10000000000000001 1 1</property>
+                                        <property name="value_pos">GTK_POS_RIGHT</property>
                                       </widget>
                                       <packing>
                                         <property name="position">1</property>
                                       </packing>
                                     </child>
-                                    <child>
-                                      <widget class="GtkLabel" id="label24">
-                                        <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Fast&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
                                   </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
                                 </child>
                                 <child>
-                                  <widget class="GtkLabel" id="label10">
+                                  <widget class="GtkVBox" id="vbox8">
                                     <property name="visible">True</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">_Threshold:</property>
-                                    <property name="use_underline">True</property>
-                                    <property name="mnemonic_widget">mouse_motion_threshold</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="position">2</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <widget class="GtkHBox" id="hbox8">
-                                    <property name="visible">True</property>
                                     <property name="spacing">2</property>
                                     <child>
-                                      <widget class="GtkLabel" id="label21">
+                                      <widget class="GtkLabel" id="mouse-threshold-label">
                                         <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Low&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
+                                        <property name="xalign">0</property>
+                                        <property name="label" translatable="yes">_Threshold:</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="mnemonic_widget">mouse-threshold-scale</property>
                                       </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                      </packing>
                                     </child>
                                     <child>
-                                      <widget class="GtkHScale" id="mouse_motion_threshold">
+                                      <widget class="GtkHScale" id="mouse-threshold-scale">
                                         <property name="visible">True</property>
                                         <property name="can_focus">True</property>
                                         <property name="tooltip" translatable="yes">The number of pixels the pointer has to moved in a short time before the acceleration starts</property>
-                                        <property name="adjustment">1 1 20 1 5 0</property>
-                                        <property name="fill_level">0</property>
+                                        <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                        <property name="adjustment">4 1 30 1 5 5</property>
                                         <property name="digits">0</property>
-                                        <property name="draw_value">False</property>
+                                        <property name="value_pos">GTK_POS_RIGHT</property>
                                       </widget>
                                       <packing>
                                         <property name="position">1</property>
                                       </packing>
                                     </child>
+                                  </widget>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkAlignment" id="alignment7">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="xscale">0</property>
                                     <child>
-                                      <widget class="GtkLabel" id="label22">
+                                      <widget class="GtkButton" id="mouse-reset">
                                         <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;High&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
+                                        <property name="can_focus">True</property>
+                                        <property name="receives_default">True</property>
+                                        <property name="tooltip" translatable="yes">Set the acceleration and threshold for the selected device to the default values</property>
+                                        <property name="label" translatable="yes">Re_set to default</property>
+                                        <property name="use_underline">True</property>
+                                        <property name="response_id">0</property>
                                       </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">2</property>
-                                      </packing>
                                     </child>
                                   </widget>
                                   <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">3</property>
+                                    <property name="position">2</property>
                                   </packing>
                                 </child>
                               </widget>
@@ -225,9 +225,9 @@
                           </widget>
                         </child>
                         <child>
-                          <widget class="GtkLabel" id="label4">
+                          <widget class="GtkLabel" id="label5">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;b&gt;Motion Settings&lt;/b&gt;</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Feedback&lt;/b&gt;</property>
                             <property name="use_markup">True</property>
                           </widget>
                           <packing>
@@ -240,323 +240,308 @@
                         <property name="position">1</property>
                       </packing>
                     </child>
+                  </widget>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Devices</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox3">
+                <property name="visible">True</property>
+                <property name="border_width">6</property>
+                <property name="spacing">12</property>
+                <child>
+                  <widget class="GtkFrame" id="frame3">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
                     <child>
-                      <widget class="GtkFrame" id="frame_dnd">
+                      <widget class="GtkAlignment" id="alignment3">
                         <property name="visible">True</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">GTK_SHADOW_NONE</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">18</property>
+                        <property name="right_padding">6</property>
                         <child>
-                          <widget class="GtkAlignment" id="alignment3">
+                          <widget class="GtkVBox" id="vbox4">
                             <property name="visible">True</property>
-                            <property name="bottom_padding">6</property>
-                            <property name="left_padding">12</property>
+                            <property name="spacing">2</property>
                             <child>
-                              <widget class="GtkVBox" id="vbox5">
+                              <widget class="GtkLabel" id="mouse-dnd-label">
                                 <property name="visible">True</property>
-                                <property name="border_width">6</property>
-                                <property name="spacing">6</property>
+                                <property name="xalign">0</property>
+                                <property name="label" translatable="yes">Thr_eshold:</property>
+                                <property name="use_underline">True</property>
+                                <property name="mnemonic_widget">mouse-dnd-threshold</property>
+                              </widget>
+                            </child>
+                            <child>
+                              <widget class="GtkHScale" id="mouse-dnd-threshold">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip" translatable="yes">The number of pixels the pointer can move before dragging</property>
+                                <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                <property name="adjustment">8 1 50 1 10 10</property>
+                                <property name="digits">0</property>
+                                <property name="value_pos">GTK_POS_RIGHT</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label6">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Drag and Drop&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkFrame" id="frame4">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment4">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">18</property>
+                        <property name="right_padding">6</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox5">
+                            <property name="visible">True</property>
+                            <property name="spacing">12</property>
+                            <child>
+                              <widget class="GtkVBox" id="vbox10">
+                                <property name="visible">True</property>
+                                <property name="spacing">2</property>
                                 <child>
-                                  <widget class="GtkLabel" id="label11">
+                                  <widget class="GtkLabel" id="mouse-double-click-time-label">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">Thr_eshold:</property>
+                                    <property name="label" translatable="yes">Ti_me:</property>
                                     <property name="use_underline">True</property>
-                                    <property name="mnemonic_widget">mouse_dnd_threshold</property>
+                                    <property name="mnemonic_widget">mouse-double-click-time</property>
                                   </widget>
                                 </child>
                                 <child>
-                                  <widget class="GtkHBox" id="hbox9">
+                                  <widget class="GtkHScale" id="mouse-double-click-time">
                                     <property name="visible">True</property>
-                                    <property name="spacing">2</property>
-                                    <child>
-                                      <widget class="GtkLabel" id="label17">
-                                        <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Low&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <widget class="GtkHScale" id="mouse_dnd_threshold">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="tooltip" translatable="yes">The number of pixels the pointer can move before dragging</property>
-                                        <property name="adjustment">1 1 50 1 5 0</property>
-                                        <property name="digits">0</property>
-                                        <property name="draw_value">False</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <widget class="GtkLabel" id="label18">
-                                        <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;High&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
+                                    <property name="can_focus">True</property>
+                                    <property name="tooltip" translatable="yes">The maximum time allowed between two clicks, in milliseconds, for them to be considered a double click</property>
+                                    <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                    <property name="adjustment">250 100 2000 10 100 100</property>
+                                    <property name="digits">0</property>
+                                    <property name="value_pos">GTK_POS_RIGHT</property>
                                   </widget>
                                   <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
                                     <property name="position">1</property>
                                   </packing>
                                 </child>
                               </widget>
                             </child>
-                          </widget>
-                        </child>
-                        <child>
-                          <widget class="GtkLabel" id="label5">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;b&gt;Drag and Drop&lt;/b&gt;</property>
-                            <property name="use_markup">True</property>
-                          </widget>
-                          <packing>
-                            <property name="type">label_item</property>
-                          </packing>
-                        </child>
-                      </widget>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <widget class="GtkFrame" id="frame_double_click">
-                        <property name="visible">True</property>
-                        <property name="label_xalign">0</property>
-                        <property name="shadow_type">GTK_SHADOW_NONE</property>
-                        <child>
-                          <widget class="GtkAlignment" id="alignment4">
-                            <property name="visible">True</property>
-                            <property name="left_padding">12</property>
                             <child>
-                              <widget class="GtkVBox" id="vbox6">
+                              <widget class="GtkVBox" id="vbox11">
                                 <property name="visible">True</property>
-                                <property name="border_width">6</property>
-                                <property name="spacing">6</property>
+                                <property name="spacing">2</property>
                                 <child>
-                                  <widget class="GtkLabel" id="label12">
+                                  <widget class="GtkLabel" id="mouse-double-click-distance-label">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">_Speed:</property>
+                                    <property name="label" translatable="yes">_Distance:</property>
                                     <property name="use_underline">True</property>
-                                    <property name="mnemonic_widget">mouse_double_click_speed</property>
+                                    <property name="mnemonic_widget">mouse-double-click-distance</property>
                                   </widget>
                                 </child>
                                 <child>
-                                  <widget class="GtkHBox" id="hbox10">
+                                  <widget class="GtkHScale" id="mouse-double-click-distance">
                                     <property name="visible">True</property>
-                                    <property name="spacing">2</property>
-                                    <child>
-                                      <widget class="GtkLabel" id="label19">
-                                        <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Slow&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <widget class="GtkHScale" id="mouse_double_click_speed">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="tooltip" translatable="yes">The maximum time allowed between two clicks for them to be considered a double click</property>
-                                        <property name="adjustment">100 100 2000 10 100 0</property>
-                                        <property name="digits">0</property>
-                                        <property name="draw_value">False</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <widget class="GtkLabel" id="label20">
-                                        <property name="visible">True</property>
-                                        <property name="label" translatable="yes">&lt;small&gt;&lt;i&gt;Fast&lt;/i&gt;&lt;/small&gt;</property>
-                                        <property name="use_markup">True</property>
-                                      </widget>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="fill">False</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
+                                    <property name="can_focus">True</property>
+                                    <property name="tooltip" translatable="yes">The maximum distance allowed between two clicks, in pixels, for them to be considered a double click</property>
+                                    <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                    <property name="adjustment">4 0 20 1 5 5</property>
+                                    <property name="digits">0</property>
+                                    <property name="value_pos">GTK_POS_RIGHT</property>
                                   </widget>
                                   <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
                                     <property name="position">1</property>
                                   </packing>
                                 </child>
                               </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
                             </child>
                           </widget>
                         </child>
-                        <child>
-                          <widget class="GtkLabel" id="label6">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;b&gt;Double Click&lt;/b&gt;</property>
-                            <property name="use_markup">True</property>
-                          </widget>
-                          <packing>
-                            <property name="type">label_item</property>
-                          </packing>
-                        </child>
                       </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label8">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Double Click&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
                       <packing>
-                        <property name="expand">False</property>
-                        <property name="position">3</property>
+                        <property name="type">label_item</property>
                       </packing>
                     </child>
                   </widget>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Behaviour</property>
-                  </widget>
                   <packing>
-                    <property name="type">tab</property>
-                    <property name="tab_fill">False</property>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
                   </packing>
                 </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Behaviour</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">1</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkHBox" id="mouse-themes-hbox">
+                <property name="visible">True</property>
+                <property name="border_width">6</property>
+                <property name="spacing">12</property>
                 <child>
-                  <widget class="GtkHBox" id="hbox2">
+                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
                     <property name="visible">True</property>
-                    <property name="border_width">12</property>
-                    <property name="spacing">12</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
                     <child>
-                      <widget class="GtkScrolledWindow" id="scrolledwindow1">
-                        <property name="width_request">100</property>
+                      <widget class="GtkTreeView" id="mouse-theme-treeview">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                        <property name="shadow_type">GTK_SHADOW_IN</property>
-                        <child>
-                          <widget class="GtkTreeView" id="treeview_cursor_theme">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="headers_visible">False</property>
-                            <property name="search_column">0</property>
-                          </widget>
-                        </child>
+                        <property name="headers_visible">False</property>
+                        <property name="headers_clickable">False</property>
                       </widget>
                     </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkVBox" id="vbox9">
+                    <property name="visible">True</property>
+                    <property name="spacing">12</property>
                     <child>
-                      <widget class="GtkVBox" id="vbox3">
+                      <widget class="GtkFrame" id="frame5">
                         <property name="visible">True</property>
-                        <property name="spacing">6</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">GTK_SHADOW_NONE</property>
                         <child>
-                          <widget class="GtkFrame" id="frame_cursor_size">
+                          <widget class="GtkAlignment" id="alignment5">
                             <property name="visible">True</property>
-                            <property name="label_xalign">0</property>
-                            <property name="shadow_type">GTK_SHADOW_NONE</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <property name="right_padding">6</property>
                             <child>
-                              <widget class="GtkAlignment" id="alignment5">
+                              <widget class="GtkHBox" id="hbox7">
                                 <property name="visible">True</property>
-                                <property name="bottom_padding">6</property>
-                                <property name="left_padding">12</property>
+                                <property name="spacing">12</property>
                                 <child>
-                                  <widget class="GtkAspectFrame" id="aspectframe1">
+                                  <widget class="GtkLabel" id="label21">
                                     <property name="visible">True</property>
-                                    <property name="border_width">6</property>
-                                    <property name="label_xalign">0</property>
-                                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                                    <property name="xalign">0</property>
-                                    <child>
-                                      <widget class="GtkHBox" id="hbox3">
-                                        <property name="visible">True</property>
-                                        <property name="spacing">12</property>
-                                        <child>
-                                          <widget class="GtkLabel" id="label13">
-                                            <property name="visible">True</property>
-                                            <property name="label" translatable="yes">Cursor _size:</property>
-                                            <property name="use_underline">True</property>
-                                            <property name="mnemonic_widget">spin_cursor_size</property>
-                                          </widget>
-                                        </child>
-                                        <child>
-                                          <widget class="GtkSpinButton" id="spin_cursor_size">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="editable">False</property>
-                                            <property name="max_length">2</property>
-                                            <property name="adjustment">24 16 48 1 10 10</property>
-                                            <property name="numeric">True</property>
-                                          </widget>
-                                          <packing>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                      </widget>
-                                    </child>
+                                    <property name="label" translatable="yes">Cursor _Size:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">mouse-cursor-size</property>
                                   </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                  </packing>
                                 </child>
+                                <child>
+                                  <widget class="GtkSpinButton" id="mouse-cursor-size">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="adjustment">24 16 48 1 11 10</property>
+                                    <property name="snap_to_ticks">True</property>
+                                    <property name="numeric">True</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
                               </widget>
                             </child>
-                            <child>
-                              <widget class="GtkLabel" id="label7">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">&lt;b&gt;Size&lt;/b&gt;</property>
-                                <property name="use_markup">True</property>
-                              </widget>
-                              <packing>
-                                <property name="type">label_item</property>
-                              </packing>
-                            </child>
                           </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label20">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Size&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </widget>
                           <packing>
-                            <property name="expand">False</property>
+                            <property name="type">label_item</property>
                           </packing>
                         </child>
+                      </widget>
+                      <packing>
+                        <property name="expand">False</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <widget class="GtkFrame" id="frame6">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">GTK_SHADOW_NONE</property>
                         <child>
-                          <widget class="GtkFrame" id="frame_preview">
+                          <widget class="GtkAlignment" id="alignment6">
                             <property name="visible">True</property>
-                            <property name="label_xalign">0</property>
-                            <property name="shadow_type">GTK_SHADOW_NONE</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <property name="right_pad