[gnome-control-center] mouse: Update from gnome-settings-daemon
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] mouse: Update from gnome-settings-daemon
- Date: Thu, 19 Apr 2012 11:02:50 +0000 (UTC)
commit be45283bb43e3734de6cc6773bc589b51d120c0f
Author: Bastien Nocera <hadess hadess net>
Date: Thu Apr 19 11:56:21 2012 +0100
mouse: Update from gnome-settings-daemon
panels/mouse/gsd-input-helper.c | 343 +++++++++++++++++++++++++++++++++++++--
panels/mouse/gsd-input-helper.h | 48 +++++-
2 files changed, 374 insertions(+), 17 deletions(-)
---
diff --git a/panels/mouse/gsd-input-helper.c b/panels/mouse/gsd-input-helper.c
index 5362701..95b1b38 100644
--- a/panels/mouse/gsd-input-helper.c
+++ b/panels/mouse/gsd-input-helper.c
@@ -25,22 +25,118 @@
#include <sys/types.h>
#include <X11/Xatom.h>
+#include <X11/extensions/XInput2.h>
#include "gsd-input-helper.h"
#define INPUT_DEVICES_SCHEMA "org.gnome.settings-daemon.peripherals.input-devices"
#define KEY_HOTPLUG_COMMAND "hotplug-command"
+typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info);
+typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice);
+
gboolean
-supports_xinput_devices (void)
+device_set_property (XDevice *xdevice,
+ const char *device_name,
+ PropertyHelper *property)
+{
+ int rc, i;
+ Atom prop;
+ Atom realtype;
+ int realformat;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+
+ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ property->name, False);
+ if (!prop)
+ return FALSE;
+
+ gdk_error_trap_push ();
+
+ rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ xdevice, prop, 0, property->nitems, False,
+ AnyPropertyType, &realtype, &realformat, &nitems,
+ &bytes_after, &data);
+
+ if (rc != Success ||
+ realtype != property->type ||
+ realformat != property->format ||
+ nitems < property->nitems) {
+ gdk_error_trap_pop_ignored ();
+ g_warning ("Error reading property \"%s\" for \"%s\"", property->name, device_name);
+ return FALSE;
+ }
+
+ for (i = 0; i < nitems; i++) {
+ switch (property->format) {
+ case 8:
+ data[i] = property->data.c[i];
+ break;
+ case 32:
+ ((long*)data)[i] = property->data.i[i];
+ break;
+ }
+ }
+
+ XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ xdevice, prop, realtype, realformat,
+ PropModeReplace, data, nitems);
+
+ if (gdk_error_trap_pop ()) {
+ g_warning ("Error in setting \"%s\" for \"%s\"", property->name, device_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+supports_xinput_devices_with_opcode (int *opcode)
{
gint op_code, event, error;
+ gboolean retval;
+
+ retval = XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ "XInputExtension",
+ &op_code,
+ &event,
+ &error);
+ if (opcode)
+ *opcode = op_code;
+
+ return retval;
+}
+
+gboolean
+supports_xinput_devices (void)
+{
+ return supports_xinput_devices_with_opcode (NULL);
+}
+
+gboolean
+supports_xinput2_devices (int *opcode)
+{
+ int major, minor;
- return XQueryExtension (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- "XInputExtension",
- &op_code,
- &event,
- &error);
+ if (supports_xinput_devices_with_opcode (opcode) == FALSE)
+ return FALSE;
+
+ gdk_error_trap_push ();
+
+ major = 2;
+ minor = 0;
+
+ if (XIQueryVersion (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &major, &minor) != Success) {
+ gdk_error_trap_pop_ignored ();
+ return FALSE;
+ }
+ gdk_error_trap_pop_ignored ();
+
+ if ((major * 1000 + minor) < (2000))
+ return FALSE;
+
+ return TRUE;
}
gboolean
@@ -51,9 +147,8 @@ device_is_touchpad (XDevice *xdevice)
unsigned long nitems, bytes_after;
unsigned char *data;
- /* FIXME
- * we don't check on the type being XI_TOUCHPAD, but having a "Synaptics Off"
- * property should be enough */
+ /* we don't check on the type being XI_TOUCHPAD here,
+ * but having a "Synaptics Off" property should be enough */
prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Off", False);
if (!prop)
@@ -73,7 +168,20 @@ device_is_touchpad (XDevice *xdevice)
}
gboolean
-touchpad_is_present (void)
+device_info_is_touchpad (XDeviceInfo *device_info)
+{
+ return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHPAD, False));
+}
+
+gboolean
+device_info_is_touchscreen (XDeviceInfo *device_info)
+{
+ return (device_info->type == XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), XI_TOUCHSCREEN, False));
+}
+
+static gboolean
+device_type_is_present (InfoIdentifyFunc info_func,
+ DeviceIdentifyFunc device_func)
{
XDeviceInfo *device_info;
gint n_devices;
@@ -92,12 +200,21 @@ touchpad_is_present (void)
for (i = 0; i < n_devices; i++) {
XDevice *device;
+ /* Check with the device info first */
+ retval = (info_func) (&device_info[i]);
+ if (retval == FALSE)
+ continue;
+
+ /* If we only have an info func, we're done checking */
+ if (device_func == NULL)
+ break;
+
gdk_error_trap_push ();
device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_info[i].id);
if (gdk_error_trap_pop () || (device == NULL))
continue;
- retval = device_is_touchpad (device);
+ retval = (device_func) (device);
if (retval) {
XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
break;
@@ -110,6 +227,175 @@ touchpad_is_present (void)
return retval;
}
+gboolean
+touchscreen_is_present (void)
+{
+ return device_type_is_present (device_info_is_touchscreen,
+ NULL);
+}
+
+gboolean
+touchpad_is_present (void)
+{
+ return device_type_is_present (device_info_is_touchpad,
+ device_is_touchpad);
+}
+
+char *
+xdevice_get_device_node (int deviceid)
+{
+ Atom prop;
+ Atom act_type;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ char *ret;
+
+ gdk_display_sync (gdk_display_get_default ());
+
+ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Node", False);
+ if (!prop)
+ return NULL;
+
+ gdk_error_trap_push ();
+
+ if (!XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ deviceid, prop, 0, 1000, False,
+ AnyPropertyType, &act_type, &act_format,
+ &nitems, &bytes_after, &data) == Success) {
+ gdk_error_trap_pop_ignored ();
+ return NULL;
+ }
+ if (gdk_error_trap_pop ())
+ goto out;
+
+ if (nitems == 0)
+ goto out;
+
+ if (act_type != XA_STRING)
+ goto out;
+
+ /* Unknown string format */
+ if (act_format != 8)
+ goto out;
+
+ ret = g_strdup ((char *) data);
+
+ XFree (data);
+ return ret;
+
+out:
+ XFree (data);
+ return NULL;
+}
+
+#define TOOL_ID_FORMAT_SIZE 32
+static int
+get_id_for_index (guchar *data,
+ guint idx)
+{
+ guchar *ptr;
+ int id;
+
+ ptr = data;
+ ptr += TOOL_ID_FORMAT_SIZE / 8 * idx;
+
+ id = *((int32_t*)ptr);
+ id = id & 0xfffff;
+
+ return id;
+}
+
+
+#define STYLUS_DEVICE_ID 0x02
+#define ERASER_DEVICE_ID 0x0A
+
+int
+xdevice_get_last_tool_id (int deviceid)
+{
+ Atom prop;
+ Atom act_type;
+ int act_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data;
+ int id;
+
+ id = -1;
+
+ gdk_display_sync (gdk_display_get_default ());
+
+ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), WACOM_SERIAL_IDS_PROP, False);
+ if (!prop)
+ return -1;
+
+ gdk_error_trap_push ();
+
+ if (!XIGetProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ deviceid, prop, 0, 1000, False,
+ AnyPropertyType, &act_type, &act_format,
+ &nitems, &bytes_after, &data) == Success) {
+ gdk_error_trap_pop_ignored ();
+ return -1;
+ }
+
+ if (gdk_error_trap_pop ())
+ goto out;
+
+ if (nitems != 4 && nitems != 5)
+ goto out;
+
+ if (act_type != XA_INTEGER)
+ goto out;
+
+ if (act_format != TOOL_ID_FORMAT_SIZE)
+ goto out;
+
+ /* item 0 = tablet ID
+ * item 1 = old device serial number (== last tool in proximity)
+ * item 2 = old hardware serial number (including tool ID)
+ * item 3 = current serial number (0 if no tool in proximity)
+ * item 4 = current tool ID (since Feb 2012)
+ *
+ * Get the current tool ID first, if available, then the old one */
+ id = 0x0;
+ if (nitems == 5)
+ id = get_id_for_index (data, 4);
+ if (id == 0x0)
+ id = get_id_for_index (data, 2);
+
+ /* That means that no tool was set down yet */
+ if (id == STYLUS_DEVICE_ID ||
+ id == ERASER_DEVICE_ID)
+ return 0x0;
+
+out:
+ XFree (data);
+ return id;
+}
+
+gboolean
+set_device_enabled (int device_id,
+ gboolean enabled)
+{
+ Atom prop;
+ guchar value;
+
+ prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Device Enabled", False);
+ if (!prop)
+ return FALSE;
+
+ gdk_error_trap_push ();
+
+ value = enabled ? 1 : 0;
+ XIChangeProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ device_id, prop, XA_INTEGER, 8, PropModeReplace, &value, 1);
+
+ if (gdk_error_trap_pop ())
+ return FALSE;
+
+ return TRUE;
+}
+
static const char *
custom_command_to_string (CustomCommand command)
{
@@ -182,3 +468,38 @@ run_custom_command (GdkDevice *device,
return (exit_status == 0);
}
+
+GList *
+get_disabled_devices (GdkDeviceManager *manager)
+{
+ XDeviceInfo *device_info;
+ gint n_devices;
+ guint i;
+ GList *ret;
+
+ ret = NULL;
+
+ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
+ if (device_info == NULL)
+ return ret;
+
+ for (i = 0; i < n_devices; i++) {
+ GdkDevice *device;
+
+ /* Ignore core devices */
+ if (device_info[i].use == IsXKeyboard ||
+ device_info[i].use == IsXPointer)
+ continue;
+
+ /* Check whether the device is actually available */
+ device = gdk_x11_device_manager_lookup (manager, device_info[i].id);
+ if (device != NULL)
+ continue;
+
+ ret = g_list_prepend (ret, GINT_TO_POINTER (device_info[i].id));
+ }
+
+ XFreeDeviceList (device_info);
+
+ return ret;
+}
diff --git a/panels/mouse/gsd-input-helper.h b/panels/mouse/gsd-input-helper.h
index a705f90..dfde51f 100644
--- a/panels/mouse/gsd-input-helper.h
+++ b/panels/mouse/gsd-input-helper.h
@@ -27,18 +27,54 @@ G_BEGIN_DECLS
#include <X11/extensions/XInput.h>
#include <X11/extensions/XIproto.h>
+#define WACOM_SERIAL_IDS_PROP "Wacom Serial IDs"
+
typedef enum {
- COMMAND_DEVICE_ADDED,
- COMMAND_DEVICE_REMOVED,
- COMMAND_DEVICE_PRESENT
+ COMMAND_DEVICE_ADDED,
+ COMMAND_DEVICE_REMOVED,
+ COMMAND_DEVICE_PRESENT
} CustomCommand;
-gboolean supports_xinput_devices (void);
-gboolean device_is_touchpad (XDevice *xdevice);
+/* Generic property setting code. Fill up the struct property with the property
+ * data and pass it into device_set_property together with the device to be
+ * changed. Note: doesn't cater for non-zero offsets yet, but we don't have
+ * any settings that require that.
+ */
+typedef struct {
+ const char *name; /* property name */
+ gint nitems; /* number of items in data */
+ gint format; /* CARD8 or CARD32 sized-items */
+ gint type; /* Atom representing data type */
+ union {
+ const gchar *c; /* 8 bit data */
+ const gint *i; /* 32 bit data */
+ } data;
+} PropertyHelper;
+
+gboolean supports_xinput_devices (void);
+gboolean supports_xinput2_devices (int *opcode);
+
+gboolean set_device_enabled (int device_id,
+ gboolean enabled);
+
+gboolean device_is_touchpad (XDevice *xdevice);
+
+gboolean device_info_is_touchpad (XDeviceInfo *device_info);
+gboolean device_info_is_touchscreen (XDeviceInfo *device_info);
+
gboolean touchpad_is_present (void);
+gboolean touchscreen_is_present (void);
+
+gboolean device_set_property (XDevice *xdevice,
+ const char *device_name,
+ PropertyHelper *property);
gboolean run_custom_command (GdkDevice *device,
- CustomCommand command);
+ CustomCommand command);
+
+GList * get_disabled_devices (GdkDeviceManager *manager);
+char * xdevice_get_device_node (int deviceid);
+int xdevice_get_last_tool_id (int deviceid);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]