[Xfce4-commits] r27233 - xfce4-settings/branches/multiple_pointers

Nick Schermer nick at xfce.org
Mon Jul 7 22:21:25 CEST 2008


Author: nick
Date: 2008-07-07 20:21:25 +0000 (Mon, 07 Jul 2008)
New Revision: 27233

Added:
   xfce4-settings/branches/multiple_pointers/Makefile
   xfce4-settings/branches/multiple_pointers/daemon.c
   xfce4-settings/branches/multiple_pointers/main.c
   xfce4-settings/branches/multiple_pointers/mouse_dialog.glade
Log:
* Import intial code

Added: xfce4-settings/branches/multiple_pointers/Makefile
===================================================================
--- xfce4-settings/branches/multiple_pointers/Makefile	                        (rev 0)
+++ xfce4-settings/branches/multiple_pointers/Makefile	2008-07-07 20:21:25 UTC (rev 27233)
@@ -0,0 +1,34 @@
+# $Id: Makefile 26813 2008-04-10 10:24:38Z nick $
+
+CC = gcc
+CFLAGS = -pipe -O -g -ggdb -fstack-protector-all -fno-inline -Wall -Werror -Wuninitialized -Winit-self -Wpointer-arith -Wsign-compare -D_FORTIFY_SOURCE=2 -DG_ENABLE_DEBUG
+
+all:
+	exo-csource --static --name=mouse_dialog_glade \
+	mouse_dialog.glade > mouse_dialog_glade.h
+	
+	$(CC) $(CFLAGS) \
+	`pkg-config --cflags --libs gtk+-2.0` \
+	`pkg-config --cflags --libs libxfcegui4-1.0` \
+	`pkg-config --cflags --libs libxfce4util-1.0` \
+	`pkg-config --cflags --libs xi` \
+	`pkg-config --cflags --libs xcursor` \
+	`pkg-config --cflags --libs libxfconf-0` \
+	`pkg-config --cflags --libs libglade-2.0` \
+	`pkg-config --cflags --libs hal` \
+	`pkg-config --cflags --libs dbus-glib-1` \
+	mouse_dialog_glade.h \
+	main.c -o xfce4-mouse-settings
+	
+	$(CC) $(CFLAGS) \
+	`pkg-config --cflags --libs gtk+-2.0` \
+	`pkg-config --cflags --libs libxfce4util-1.0` \
+	`pkg-config --cflags --libs xi` \
+	`pkg-config --cflags --libs xcursor` \
+	`pkg-config --cflags --libs libxfconf-0` \
+	`pkg-config --cflags --libs hal` \
+	`pkg-config --cflags --libs dbus-glib-1` \
+	daemon.c -o xfce4-mouse-daemon
+
+clean:
+	rm -f xfce-settings-mouse2

Added: xfce4-settings/branches/multiple_pointers/daemon.c
===================================================================
--- xfce4-settings/branches/multiple_pointers/daemon.c	                        (rev 0)
+++ xfce4-settings/branches/multiple_pointers/daemon.c	2008-07-07 20:21:25 UTC (rev 27233)
@@ -0,0 +1,513 @@
+/*
+ *  Copyright (c) 2008 Nick Schermer <nick 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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xfconf/xfconf.h>
+#include <libxfce4util/libxfce4util.h>
+#include <gtk/gtk.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#include <X11/Xcursor/Xcursor.h>
+#include <gdk/gdkx.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <hal/libhal.h>
+
+#define LOCALEDIR ""
+#define GETTEXT_PACKAGE "gettext"
+#define MAX_DENOMINATOR (100.00)
+
+
+
+/* source id to delay a channel restore when a device is added */
+static guint device_added_timeout_id = 0;
+
+
+
+static void
+mouse_daemon_change_button_mapping (XDeviceInfo *device_info,
+                                    XDevice     *device,
+                                    Display     *xdisplay,
+                                    gboolean     right_handed)
+{
+    XAnyClassPtr  ptr;
+    gshort        num_buttons;
+    guchar       *buttonmap;
+    gint          id_1, id_3;
+    gint          n;
+
+    /* get the device classes */
+    ptr = device_info->inputclassinfo;
+
+    /* search the classes for the number of buttons */
+    for (n = 0, num_buttons = 0; n < device_info->num_classes; n++)
+    {
+        /* 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);
+    }
+
+    if (G_LIKELY (num_buttons > 0))
+    {
+        /* allocate the button map */
+        buttonmap = g_new0 (guchar, num_buttons);
+
+        /* get the button mapping */
+        XGetDeviceButtonMapping (xdisplay, device, buttonmap, num_buttons);
+
+        /* figure out the position of the first and second/third button in the map */
+        for (n = 0, id_1 = id_3 = -1; n < num_buttons; n++)
+        {
+            if (buttonmap[n] == 1)
+                id_1 = n;
+            else if (buttonmap[n] == (num_buttons < 3 ? 2 : 3))
+                id_3 = n;
+        }
+
+        /* only change the map when id_1 and id_3 where found */
+        if (G_LIKELY (id_1 != -1 && id_3 != -1))
+        {
+            /* check if we need to change the buttonmap */
+            if ((!right_handed && (id_1 < id_3)) || (right_handed && (id_1 > id_3)))
+            {
+                /* swap the left and right button */
+                buttonmap[id_1] = (num_buttons < 3 ? 2 : 3);
+                buttonmap[id_3] = 1;
+
+                /* set the new button mapping */
+                XSetDeviceButtonMapping (xdisplay, device, buttonmap, num_buttons);
+            }
+        }
+
+        /* cleanup */
+        g_free (buttonmap);
+    }
+}
+
+
+
+static gint
+mouse_daemon_gcd (gint num,
+                  gint denom)
+{
+  /* calc the greatest common divisor using euclidean's algorithm */
+  return (denom != 0 ? mouse_daemon_gcd (denom, num % denom) : num);
+}
+
+
+
+static void
+mouse_daemon_change_feedback (XDevice *device,
+                              Display *xdisplay,
+                              gint     threshold,
+                              gdouble  acceleration)
+{
+    XFeedbackState      *states;
+    gint                 num_feedbacks;
+    XPtrFeedbackControl  feedback;
+    gint                 n;
+    gulong               mask = 0;
+    gint                 num, denom, gcd;
+
+
+    /* get the feedback states for this device */
+    states = XGetFeedbackControl (xdisplay, device, &num_feedbacks);
+
+    if (G_LIKELY (states))
+    {
+        /* get the pointer feedback class */
+        for (n = 0; n < num_feedbacks; n++)
+        {
+            /* find the pointer feedback class */
+            if (states->class == PtrFeedbackClass)
+            {
+                if (acceleration > 0)
+                {
+                    /* calculate the faction of the acceleration */
+                    num = acceleration * MAX_DENOMINATOR;
+                    denom = MAX_DENOMINATOR;
+                    gcd = mouse_daemon_gcd (num, denom);
+                    num /= gcd;
+                    denom /= gcd;
+
+                    /* set the mask */
+                    mask |= DvAccelNum | DvAccelDenom;
+                }
+                else
+                {
+                    /* nothing special */
+                    num = denom = 1;
+                }
+
+                /* setup the mask for the threshold */
+                if (threshold != -1)
+                    mask |= DvThreshold;
+
+                /* create a new feedback */
+                feedback.class      = PtrFeedbackClass;
+                feedback.length     = sizeof (XPtrFeedbackControl);
+                feedback.id         = states->id;
+                feedback.threshold  = threshold;
+                feedback.accelNum   = num;
+                feedback.accelDenom = denom;
+
+                /* change feedback for this device */
+                XChangeFeedbackControl (xdisplay, device, mask, (XFeedbackControl *) &feedback);
+
+                /* done */
+                break;
+            }
+
+            /* advance the offset */
+            states = (XFeedbackState *) ((gchar *) states + states->length);
+        }
+
+        /* cleanup */
+        XFreeFeedbackList (states);
+    }
+}
+
+
+
+static gchar *
+mouse_daemon_device_xfconf_name (const gchar *name)
+{
+  GString     *string;
+  const gchar *p;
+
+  /* NOTE: this function is also in the mouse dialog code
+   *       and they have to be 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 == '-')
+        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_daemon_restore_devices (XfconfChannel *channel)
+{
+    Display     *xdisplay;
+    XDeviceInfo *device_list, *device_info;
+    XDevice     *device;
+    gint         n, ndevices;
+    gchar       *righthanded_str;
+    gchar       *threshold_str;
+    gchar       *acceleration_str;
+    gchar       *device_name;
+
+    /* get the x display */
+    xdisplay = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
+
+    /* get all the registered devices */
+    device_list = XListInputDevices (xdisplay, &ndevices);
+
+    for (n = 0; n < ndevices; n++)
+    {
+        /* get the device info */
+        device_info = &device_list[n];
+
+        /* filter out the pointer devices */
+        if (device_info->use == IsXExtensionPointer)
+        {
+            /* open the device */
+            device = XOpenDevice (xdisplay, device_info->id);
+            if (G_LIKELY (device))
+            {
+                /* get a clean device name */
+                device_name = mouse_daemon_device_xfconf_name (device_info->name);
+
+                /* create righthanded property string */
+                righthanded_str = g_strdup_printf ("/Pointers/%s/RightHanded", device_name);
+
+                /* check if we have a property for this device, else continue */
+                if (xfconf_channel_has_property (channel, righthanded_str))
+                {
+                    /* restore the button mapping */
+                    mouse_daemon_change_button_mapping (device_info, device, xdisplay,
+                                                        xfconf_channel_get_bool (channel, righthanded_str, TRUE));
+
+                    /* create property names */
+                    threshold_str = g_strdup_printf ("/Pointers/%s/Threshold", device_name);
+                    acceleration_str = g_strdup_printf ("/Pointers/%s/Acceleration", device_name);
+
+                    /* restore the pointer feedback */
+                    mouse_daemon_change_feedback (device, xdisplay,
+                                                  xfconf_channel_get_int (channel, threshold_str, -1),
+                                                  xfconf_channel_get_double (channel, acceleration_str, -1.00));
+
+                    /* cleanup */
+                    g_free (threshold_str);
+                    g_free (acceleration_str);
+                }
+
+                /* cleanup */
+                g_free (righthanded_str);
+                g_free (device_name);
+
+                /* close the device */
+                XCloseDevice (xdisplay, device);
+            }
+        }
+    }
+
+    /* cleanup */
+    XFreeDeviceList (device_list);
+}
+
+
+
+static void
+mouse_daemon_channel_property_changed (XfconfChannel *channel,
+                                       const gchar   *property_name,
+                                       const GValue  *value)
+{
+    Display      *xdisplay;
+    XDeviceInfo  *device_list, *device_info;
+    XDevice      *device;
+    gint          n, ndevices;
+    gchar       **names;
+    gchar        *device_name;
+
+    /* check if this looks like a pointer property */
+    if (strncmp (property_name, "/Pointers/", 10) != 0)
+        return;
+
+    /* split the property name */
+    names = g_strsplit (property_name + 10, "/", -1);
+
+    /* check if splitting worked */
+    if (names && g_strv_length (names) == 2)
+    {
+        /* get the x display */
+        xdisplay = gdk_x11_display_get_xdisplay (gdk_display_get_default ());
+
+        /* get all the registered devices */
+        device_list = XListInputDevices (xdisplay, &ndevices);
+
+        for (n = 0; n < ndevices; n++)
+        {
+            /* get the device info */
+            device_info = &device_list[n];
+
+            /* find the pointer device */
+            if (device_info->use == IsXExtensionPointer)
+            {
+                /* create a valid xfconf device name */
+                device_name = mouse_daemon_device_xfconf_name (device_info->name);
+
+                /* check if this is the device that's been changed */
+                if (strcmp (names[0], device_name) == 0)
+                {
+                    /* open the device */
+                    device = XOpenDevice (xdisplay, device_info->id);
+                    if (G_LIKELY (device))
+                    {
+                        /* update the right property */
+                        if (strcmp (names[1], "RightHanded") == 0)
+                            mouse_daemon_change_button_mapping (device_info, device, xdisplay, g_value_get_boolean (value));
+                        else if (strcmp (names[1], "Threshold") == 0)
+                            mouse_daemon_change_feedback (device, xdisplay, g_value_get_int (value), -1);
+                        else if (strcmp (names[1], "Acceleration") == 0)
+                            mouse_daemon_change_feedback (device, xdisplay, -1, g_value_get_double (value));
+
+                        /* close the device */
+                        XCloseDevice (xdisplay, device);
+                    }
+
+                    /* stop searching */
+                    n = ndevices;
+                }
+
+                /* cleanup */
+                g_free (device_name);
+            }
+        }
+
+        /* cleanup */
+        XFreeDeviceList (device_list);
+    }
+
+    /* cleanup */
+    g_strfreev (names);
+}
+
+
+
+static gboolean
+mouse_daemon_device_added_timeout (gpointer user_data)
+{
+    XfconfChannel *channel = XFCONF_CHANNEL (user_data);
+
+    GDK_THREADS_ENTER ();
+
+    /* restore the devices */
+    mouse_daemon_restore_devices (channel);
+
+    GDK_THREADS_LEAVE ();
+
+    return FALSE;
+}
+
+
+
+static void
+mouse_daemon_device_added_timeout_destroyed (gpointer user_data)
+{
+    /* reset the timeout id */
+    device_added_timeout_id = 0;
+}
+
+
+
+static void
+mouse_daemon_device_added (LibHalContext *context,
+                           const gchar   *udi)
+{
+    XfconfChannel *channel;
+
+    /* check if an input device has been added and no timeout is running */
+    if (libhal_device_query_capability (context, udi, "input", NULL)
+        && device_added_timeout_id == 0)
+    {
+        /* get the channel */
+        channel = libhal_ctx_get_user_data (context);
+
+        /* queue a new timeout */
+        device_added_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 1000, mouse_daemon_device_added_timeout,
+                                                      channel, mouse_daemon_device_added_timeout_destroyed);
+    }
+}
+
+
+
+gint
+main(gint argc, gchar **argv)
+{
+    XfconfChannel  *channel;
+    DBusConnection *connection;
+    LibHalContext  *context = NULL;
+    DBusError       derror;
+
+    /* setup translation domain */
+    xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
+
+    /* initialize gtk */
+    gtk_init (&argc, &argv);
+
+    /* initialize xfconf */
+    xfconf_init (NULL);
+
+    /* open the xsettings channel */
+    channel = xfconf_channel_new ("xsettings");
+
+    if (G_LIKELY (channel))
+    {
+        /* restore */
+        mouse_daemon_restore_devices (channel);
+
+        /* monitor the channel */
+        g_signal_connect (G_OBJECT (channel), "property-changed", G_CALLBACK (mouse_daemon_channel_property_changed), NULL);
+
+        /* 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, channel);
+
+                /* 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_daemon_device_added);
+                    }
+                    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);
+        }
+
+        /* enter main loop */
+        gtk_main ();
+
+        /* release the channel */
+        g_object_unref (G_OBJECT (channel));
+    }
+
+    /* shutdown xfconf */
+    xfconf_shutdown ();
+
+    return EXIT_SUCCESS;
+}

Added: xfce4-settings/branches/multiple_pointers/main.c
===================================================================
--- xfce4-settings/branches/multiple_pointers/main.c	                        (rev 0)
+++ xfce4-settings/branches/multiple_pointers/main.c	2008-07-07 20:21:25 UTC (rev 27233)
@@ -0,0 +1,1112 @@
+/*
+ *  Copyright (c) 2008 Nick Schermer <nick 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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+#include <xfconf/xfconf.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput.h>
+#include <X11/Xcursor/Xcursor.h>
+#include <gdk/gdkx.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <hal/libhal.h>
+
+#include "mouse_dialog_glade.h"
+
+#define LOCALEDIR ""
+#define GETTEXT_PACKAGE "gettext"
+#define PACKAGE_VERSION "4.8.0"
+#define PACKAGE_BUGREPORT "bugzilla.xfce.org"
+
+/* settings */
+#define PREVIEW_ROWS    (3)
+#define PREVIEW_COLUMNS (6)
+#define PREVIEW_SIZE    (24)
+#define PREVIEW_SPACING (2)
+
+
+/* global settings channel */
+XfconfChannel *channel;
+
+/* lock counter to avoid signals during updates */
+static gint locked = 0;
+
+/* the display for this window */
+static GdkDisplay *display;
+
+/* device update id */
+static guint device_changed_timeout_id = 0;
+
+/* option entries */
+static gboolean opt_version = FALSE;
+
+static GOptionEntry option_entries[] =
+{
+    { "version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version, N_("Version information"), NULL },
+    { NULL }
+};
+
+
+
+/* icon names for the preview widget */
+static const gchar *preview_names[] = {
+    "left_ptr",            "left_ptr_watch",    "watch",             "hand2",
+    "question_arrow",      "sb_h_double_arrow", "sb_v_double_arrow", "bottom_left_corner",
+    "bottom_right_corner", "fleur",             "pirate",            "cross",
+    "X_cursor",            "right_ptr",         "right_side",        "right_tee",
+    "sb_right_arrow",      "sb_right_tee",      "base_arrow_down",   "base_arrow_up",
+    "bottom_side",         "bottom_tee",        "center_ptr",        "circle",
+    "dot",                 "dot_box_mask",      "dot_box_mask",      "double_arrow",
+    "draped_box",          "left_side",         "left_tee",          "ll_angle",
+    "top_side",            "top_tee"
+};
+
+
+
+enum
+{
+    COLUMN_DEVICE_ICON,
+    COLUMN_DEVICE_NAME,
+    COLUMN_DEVICE_DISPLAY_NAME,
+    COLUMN_DEVICE_XID,
+    COLUMN_DEVICE_NBUTTONS,
+    N_DEVICE_COLUMNS
+};
+
+enum
+{
+    COLUMN_THEME_PIXBUF,
+    COLUMN_THEME_PATH,
+    COLUMN_THEME_NAME,
+    COLUMN_THEME_DISPLAY_NAME,
+    COLUMN_THEME_COMMENT,
+    N_THEME_COLUMNS
+};
+
+
+
+static GdkPixbuf *
+mouse_settings_themes_pixbuf_from_filename (const gchar *filename,
+                                            guint        size)
+{
+    XcursorImage *image;
+    GdkPixbuf    *scaled, *pixbuf = NULL;
+    gsize         bsize;
+    guchar       *buffer, *p, tmp;
+    gdouble       wratio, hratio;
+    gint          dest_width, dest_height;
+
+    /* load the image */
+    image = XcursorFilenameLoadImage (filename, size);
+    if (G_LIKELY (image))
+    {
+        /* buffer size */
+        bsize = image->width * image->height * 4;
+
+        /* allocate buffer */
+        buffer = g_malloc (bsize);
+
+        /* copy pixel data to buffer */
+        memcpy (buffer, image->pixels, bsize);
+
+        /* swap bits */
+        for (p = buffer; p < buffer + bsize; p += 4)
+        {
+            tmp = p[0];
+            p[0] = p[2];
+            p[2] = tmp;
+        }
+
+        /* create pixbuf */
+        pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
+                                           8, image->width, image->height,
+                                           4 * image->width,
+                                           (GdkPixbufDestroyNotify) g_free, NULL);
+
+        /* don't leak when creating the pixbuf failed */
+        if (G_UNLIKELY (pixbuf == NULL))
+            g_free (buffer);
+
+        /* scale pixbuf if needed */
+        if (pixbuf && (image->height > size || image->width > size))
+        {
+            /* calculate the ratio */
+            wratio = (gdouble) image->width / (gdouble) size;
+            hratio = (gdouble) image->height / (gdouble) size;
+
+            /* init */
+            dest_width = dest_height = size;
+
+            /* set dest size */
+            if (hratio > wratio)
+                dest_width  = rint (image->width / hratio);
+            else
+                dest_height = rint (image->height / wratio);
+
+            /* scale pixbuf */
+            scaled = gdk_pixbuf_scale_simple (pixbuf, MAX (dest_width, 1), MAX (dest_height, 1), GDK_INTERP_BILINEAR);
+
+            /* release and set scaled pixbuf */
+            g_object_unref (G_OBJECT (pixbuf));
+            pixbuf = scaled;
+        }
+
+        /* cleanup */
+        XcursorImageDestroy (image);
+    }
+
+    return pixbuf;
+}
+
+
+
+static GdkPixbuf *
+mouse_settings_themes_preview_icon (const gchar *path)
+{
+    GdkPixbuf *pixbuf = NULL;
+    gchar     *filename;
+
+    /* we only try the normal cursor, it is (most likely) always there */
+    filename = g_build_filename (path, "left_ptr", NULL);
+
+    /* try to load the pixbuf */
+    pixbuf = mouse_settings_themes_pixbuf_from_filename (filename, PREVIEW_SIZE);
+
+    /* cleanup */
+    g_free (filename);
+
+    return pixbuf;
+}
+
+
+
+static void
+mouse_settings_themes_preview_image (const gchar *path,
+                                     GtkImage    *image)
+{
+    GdkPixbuf *pixbuf;
+    GdkPixbuf *preview;
+    guint      i, position;
+    gchar     *filename;
+    gint       dest_x, dest_y;
+
+    /* create an empty preview image */
+    preview = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+                              (PREVIEW_SIZE + PREVIEW_SPACING) * PREVIEW_COLUMNS - PREVIEW_SPACING,
+                              (PREVIEW_SIZE + PREVIEW_SPACING) * PREVIEW_ROWS - PREVIEW_SPACING);
+
+    if (G_LIKELY (preview))
+    {
+        /* make the pixbuf transparent */
+        gdk_pixbuf_fill (preview, 0x00000000);
+
+        for (i = 0, position = 0; i < G_N_ELEMENTS (preview_names); i++)
+        {
+            /* create cursor filename and try to load the pixbuf */
+            filename = g_build_filename (path, preview_names[i], NULL);
+            pixbuf = mouse_settings_themes_pixbuf_from_filename (filename, PREVIEW_SIZE);
+            g_free (filename);
+
+            if (G_LIKELY (pixbuf))
+            {
+                /* calculate the icon position */
+                dest_x = (position % PREVIEW_COLUMNS) * (PREVIEW_SIZE + PREVIEW_SPACING);
+                dest_y = (position / PREVIEW_COLUMNS) * (PREVIEW_SIZE + PREVIEW_SPACING);
+
+                /* render it in the preview */
+                gdk_pixbuf_scale (pixbuf, preview, dest_x, dest_y,
+                                  gdk_pixbuf_get_width (pixbuf),
+                                  gdk_pixbuf_get_height (pixbuf),
+                                  dest_x, dest_y,
+                                  1.00, 1.00, GDK_INTERP_BILINEAR);
+
+
+                /* release the pixbuf */
+                g_object_unref (G_OBJECT (pixbuf));
+
+                /* break if we've added enough icons */
+                if (++position >= PREVIEW_ROWS * PREVIEW_COLUMNS)
+                    break;
+            }
+        }
+
+        /* set the image */
+        gtk_image_set_from_pixbuf (GTK_IMAGE (image), preview);
+
+        /* release the pixbuf */
+        g_object_unref (G_OBJECT (preview));
+    }
+    else
+    {
+        /* clear the image */
+        gtk_image_clear (GTK_IMAGE (image));
+    }
+}
+
+
+
+static void
+mouse_settings_themes_selection_changed (GtkTreeSelection *selection,
+                                         GladeXML       *gxml)
+{
+    GtkTreeModel *model;
+    GtkTreeIter   iter;
+    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 (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";
+#else
+    path = XcursorLibraryPath ();
+#endif
+
+    /* split the paths */
+    basedirs = g_strsplit (path, ":", -1);
+
+    /* get the active theme */
+    active_theme = xfconf_channel_get_string (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_DISPLAY_NAME, _("Default"), -1);
+
+    /* 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))
+    {
+        /* walk the base directories */
+        for (i = 0; basedirs[i] != NULL; i++)
+        {
+            /* init */
+            homedir = NULL;
+
+            /* parse the homedir if needed */
+            if (strstr (basedirs[i], "~/") != NULL)
+                path = homedir = g_strconcat (g_get_home_dir (), basedirs[i] + 1, NULL);
+            else
+                path = basedirs[i];
+
+            /* open directory */
+            dir = g_dir_open (path, 0, NULL);
+            if (G_LIKELY (dir))
+            {
+                for (;;)
+                {
+                    /* get the directory name */
+                    theme = g_dir_read_name (dir);
+                    if (G_UNLIKELY (theme == NULL))
+                        break;
+
+                    /* build the full cursor path */
+                    filename = g_build_filename (path, theme, "cursors", NULL);
+
+                    /* check if it looks like a cursor theme */
+                    if (g_file_test (filename, G_FILE_TEST_IS_DIR))
+                    {
+                        /* try to load a pixbuf */
+                        pixbuf = mouse_settings_themes_preview_icon (filename);
+
+                        /* insert in the store */
+                        gtk_list_store_insert_with_values (store, &iter, position++,
+                                                           COLUMN_THEME_PIXBUF, pixbuf,
+                                                           COLUMN_THEME_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)
+                        {
+                            gtk_tree_path_free (active_path);
+                            active_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+                        }
+
+                        /* release pixbuf */
+                        if (G_LIKELY (pixbuf))
+                            g_object_unref (G_OBJECT (pixbuf));
+
+                        /* check for a index.theme file for additional information */
+                        index_file = g_build_filename (path, theme, "index.theme", NULL);
+                        if (g_file_test (index_file, G_FILE_TEST_IS_REGULAR))
+                        {
+                            /* open theme desktop file */
+                            rc = xfce_rc_simple_open (index_file, TRUE);
+                            if (G_LIKELY (rc))
+                            {
+                                /* check for the theme group */
+                                if (xfce_rc_has_group (rc, "Icon Theme"))
+                                {
+                                    /* set group */
+                                    xfce_rc_set_group (rc, "Icon Theme");
+
+                                    /* read values */
+                                    name = xfce_rc_read_entry (rc, "Name", theme);
+                                    comment = xfce_rc_read_entry (rc, "Comment", NULL);
+
+                                    /* update store */
+                                    gtk_list_store_set (store, &iter,
+                                                        COLUMN_THEME_DISPLAY_NAME, name,
+                                                        COLUMN_THEME_COMMENT, comment, -1);
+                                }
+
+                                /* close rc file */
+                                xfce_rc_close (rc);
+                            }
+                        }
+
+                        /* cleanup */
+                        g_free (index_file);
+                    }
+
+                    /* cleanup */
+                    g_free (filename);
+                }
+
+                /* close directory */
+                g_dir_close (dir);
+            }
+
+            /* cleanup */
+            g_free (homedir);
+        }
+
+        /* cleanup */
+        g_strfreev (basedirs);
+    }
+
+    /* cleanup */
+    g_free (active_theme);
+
+    /* 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));
+}
+
+
+
+static void
+mouse_settings_device_selection_changed (GtkTreeSelection *selection,
+                                         GladeXML         *gxml)
+{
+    gint               nbuttons;
+    Display           *xdisplay;
+    XDevice           *device;
+    XFeedbackState    *states;
+    gint               nstates;
+    XPtrFeedbackState *state;
+    gint               i;
+    guchar            *buttonmap;
+    gint               id_1 = 0, id_3 = 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 device id and number of buttons */
+        gtk_tree_model_get (model, &iter, COLUMN_DEVICE_XID, &xid,
+                            COLUMN_DEVICE_NBUTTONS, &nbuttons, -1);
+
+        /* get the x display */
+        xdisplay = gdk_x11_display_get_xdisplay (display);
+
+        /* open the device */
+        device = XOpenDevice (xdisplay, xid);
+
+        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;
+            }
+
+            /* 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 orientation */
+    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);
+
+    /* 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 void
+mouse_settings_device_save (GladeXML *gxml)
+{
+    GtkWidget        *treeview;
+    GtkTreeSelection *selection;
+    GtkTreeModel     *model;
+    GtkTreeIter       iter;
+    gboolean          has_selection;
+    gchar            *name;
+    GtkWidget        *widget;
+    gchar            *property_name;
+    gboolean          righthanded;
+    gint              threshold;
+    gdouble           acceleration;
+
+    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 orientation */
+            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 (channel, property_name, TRUE) != righthanded)
+                xfconf_channel_set_bool (channel, property_name, righthanded);
+            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 (channel, property_name, -1) != threshold)
+                xfconf_channel_set_int (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 (channel, property_name, -1) != acceleration)
+                xfconf_channel_set_double (channel, property_name, acceleration);
+            g_free (property_name);
+
+            /* cleanup */
+            g_free (name);
+        }
+    }
+}
+
+
+
+static gchar *
+mouse_settings_device_xfconf_name (const gchar *name)
+{
+  GString     *string;
+  const gchar *p;
+
+  /* NOTE: this function is also in the mouse dialog code
+   *       and they have to be 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;
+    gchar             *device_name;
+
+    /* lock */
+    locked++;
+
+    /* get the treeview */
+    treeview = glade_xml_get_widget (gxml, "mouse-devices-treeview");
+
+    /* 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);
+    }
+
+    /* get the x display */
+    xdisplay = gdk_x11_display_get_xdisplay (display);
+
+    /* get all the registered devices */
+    device_list = XListInputDevices (xdisplay, &ndevices);
+
+    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));
+
+    if (G_LIKELY (create_store))
+    {
+        /* 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);
+    }
+
+    /* 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);
+
+    /* unlock */
+    locked--;
+}
+
+
+
+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_timeout_destroyed (gpointer user_data)
+{
+    /* reset the timeout id */
+    device_changed_timeout_id = 0;
+}
+
+
+
+static void
+mouse_settings_device_list_changed (LibHalContext *context,
+                                    const gchar   *udi)
+{
+    GladeXML *gxml;
+
+    /* queue a new timeout if none is set */
+    if (device_changed_timeout_id == 0)
+    {
+        /* get the user data */
+        gxml = libhal_ctx_get_user_data (context);
+
+        /* update the dialog in 1 second */
+        device_changed_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, 1000, mouse_settings_device_list_changed_timeout,
+                                                        gxml, mouse_settings_device_list_changed_timeout_destroyed);
+    }
+}
+
+
+
+gint
+main(gint argc, gchar **argv)
+{
+    GtkWidget      *dialog;
+    GladeXML       *gxml;
+    GError         *error = NULL;
+    GtkAdjustment  *adjustment;
+    GtkWidget      *widget;
+    DBusConnection *connection;
+    LibHalContext  *context = NULL;
+    DBusError       derror;
+
+    /* setup translation domain */
+    xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
+
+    /* initialize Gtk+ */
+    if (!gtk_init_with_args (&argc, &argv, "", option_entries, GETTEXT_PACKAGE, &error))
+    {
+        if (G_LIKELY (error == NULL))
+        {
+            g_critical (_("Failed to open display"));
+        }
+        else
+        {
+            /* show error message */
+            g_critical (error->message);
+
+            /* cleanup */
+            g_error_free (error);
+        }
+
+        return EXIT_FAILURE;
+    }
+
+    /* print version information */
+    if (G_UNLIKELY (opt_version))
+    {
+        g_print ("Xfce4-mouse-settings %s (Xfce %s)\n\n", PACKAGE_VERSION, xfce_version_string ());
+        g_print ("%s\n", "Copyright (c) 2004-2008");
+        g_print ("\t%s\n\n", _("The Xfce development team. All rights reserved."));
+        g_print (_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
+        g_print ("\n");
+
+        return EXIT_SUCCESS;
+    }
+
+    /* initialize xfconf */
+    xfconf_init (NULL);
+
+    /* open the xsettings channel */
+    channel = xfconf_channel_new ("xsettings");
+
+    if (G_LIKELY (channel))
+    {
+        /* load the glade xml file */
+        gxml = glade_xml_new_from_buffer (mouse_dialog_glade, mouse_dialog_glade_length, NULL, NULL);
+        if (G_LIKELY (gxml))
+        {
+            /* lock */
+            locked++;
+
+            /* 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);
+
+            /* 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 (channel, "/Gtk/CursorThemeSize", G_TYPE_INT, G_OBJECT (widget), "value");
+
+            /* 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 (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 (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 (channel, "/Net/DoubleClickDistance", G_TYPE_INT, G_OBJECT (adjustment), "value");
+
+            /* gtk the dialog */
+            dialog = glade_xml_get_widget (gxml, "mouse-dialog");
+            gtk_window_set_default_size (GTK_WINDOW (dialog), 480, -1);
+
+            /* 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);
+            }
+
+            /* unlock */
+            locked--;
+
+            /* show the dialog */
+            gtk_dialog_run (GTK_DIALOG (dialog));
+
+            /* 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 (device_changed_timeout_id != 0))
+                g_source_remove (device_changed_timeout_id);
+
+            /* destroy the dialog */
+            gtk_widget_destroy (GTK_WIDGET (dialog));
+
+            /* release the glade xml */
+            g_object_unref (G_OBJECT (gxml));
+        }
+
+        /* release the channel */
+        g_object_unref (G_OBJECT (channel));
+    }
+
+    /* shutdown xfconf */
+    xfconf_shutdown ();
+
+    return EXIT_SUCCESS;
+}

Added: xfce4-settings/branches/multiple_pointers/mouse_dialog.glade
===================================================================
--- xfce4-settings/branches/multiple_pointers/mouse_dialog.glade	                        (rev 0)
+++ xfce4-settings/branches/multiple_pointers/mouse_dialog.glade	2008-07-07 20:21:25 UTC (rev 27233)
@@ -0,0 +1,556 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Mon Jul  7 22:16:43 2008 -->
+<glade-interface>
+  <requires lib="xfce4"/>
+  <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="icon_name">input-mouse</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="GtkNotebook" id="notebook1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="border_width">6</property>
+            <child>
+              <widget class="GtkHBox" id="hbox1">
+                <property name="visible">True</property>
+                <property name="border_width">6</property>
+                <property name="spacing">12</property>
+                <child>
+                  <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                    <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="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="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <child>
+                              <widget class="GtkVBox" id="vbox2">
+                                <property name="visible">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>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label4">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Orientation&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="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="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <child>
+                              <widget class="GtkVBox" id="vbox6">
+                                <property name="visible">True</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <widget class="GtkVBox" id="vbox7">
+                                    <property name="visible">True</property>
+                                    <property name="spacing">2</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="mouse-acceleration-label">
+                                        <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-acceleration-scale</property>
+                                      </widget>
+                                    </child>
+                                    <child>
+                                      <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="update_policy">GTK_UPDATE_DELAYED</property>
+                                        <property name="adjustment">1 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>
+                                  </widget>
+                                </child>
+                                <child>
+                                  <widget class="GtkVBox" id="vbox8">
+                                    <property name="visible">True</property>
+                                    <property name="spacing">2</property>
+                                    <child>
+                                      <widget class="GtkLabel" id="mouse-threshold-label">
+                                        <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-threshold-scale</property>
+                                      </widget>
+                                    </child>
+                                    <child>
+                                      <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="update_policy">GTK_UPDATE_DELAYED</property>
+                                        <property name="adjustment">10 1 30 1 5 5</property>
+                                        <property name="digits">0</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>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label5">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Motion&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">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="GtkAlignment" id="alignment3">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">18</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox4">
+                            <property name="visible">True</property>
+                            <property name="spacing">2</property>
+                            <child>
+                              <widget class="GtkLabel" id="mouse-dnd-label">
+                                <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-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">1 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>
+                        <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="mouse-double-click-time-label">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">Ti_me:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">mouse-double-click-time</property>
+                                  </widget>
+                                </child>
+                                <child>
+                                  <widget class="GtkHScale" id="mouse-double-click-time">
+                                    <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="update_policy">GTK_UPDATE_DELAYED</property>
+                                    <property name="adjustment">1000 100 2000 10 100 100</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>
+                            <child>
+                              <widget class="GtkVBox" id="vbox11">
+                                <property name="visible">True</property>
+                                <property name="spacing">2</property>
+                                <child>
+                                  <widget class="GtkLabel" id="mouse-double-click-distance-label">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">_Distance:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">mouse-double-click-distance</property>
+                                  </widget>
+                                </child>
+                                <child>
+                                  <widget class="GtkHScale" id="mouse-double-click-distance">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="tooltip" translatable="yes">The maximum distance allowed between two clicks for them to be considered a double click</property>
+                                    <property name="update_policy">GTK_UPDATE_DELAYED</property>
+                                    <property name="adjustment">5 0 20 1 5 5</property>
+                                    <property name="digits">0</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>
+                          </widget>
+                        </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="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <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">Settings</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="hbox6">
+                <property name="visible">True</property>
+                <property name="border_width">6</property>
+                <property name="spacing">12</property>
+                <child>
+                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
+                    <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_ETCHED_IN</property>
+                    <child>
+                      <widget class="GtkTreeView" id="mouse-theme-treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <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="GtkFrame" id="frame5">
+                        <property name="visible">True</property>
+                        <property name="label_xalign">0</property>
+                        <property name="shadow_type">GTK_SHADOW_NONE</property>
+                        <child>
+                          <widget class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <child>
+                              <widget class="GtkHBox" id="hbox7">
+                                <property name="visible">True</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <widget class="GtkLabel" id="label21">
+                                    <property name="visible">True</property>
+                                    <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>
+                          </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="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="GtkAlignment" id="alignment6">
+                            <property name="visible">True</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">18</property>
+                            <child>
+                              <widget class="GtkImage" id="mouse-theme-preview">
+                                <property name="visible">True</property>
+                                <property name="stock">gtk-missing-image</property>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label22">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Preview&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">1</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Theme</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">2</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="label" translatable="yes">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>



More information about the Xfce4-commits mailing list