[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"><b>Orientation</b></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"><b>Motion</b></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"><b>Drag and Drop</b></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"><b>Double Click</b></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"><b>Size</b></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"><b>Preview</b></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