From 1ffb3ffdc1d598d408eee68c252c3b5dc282212f Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 14 Dec 2011 18:55:43 +0000 Subject: [PATCH] wacom: Update from gnome-settings-daemon --- panels/wacom/gsd-input-helper.c | 63 +++++++++++++++ panels/wacom/gsd-input-helper.h | 7 +- panels/wacom/gsd-wacom-device.c | 135 ++++++++++++++++++++++++++++++-- panels/wacom/gsd-wacom-device.h | 2 + 4 files changed, 199 insertions(+), 8 deletions(-) diff --git a/panels/wacom/gsd-input-helper.c b/panels/wacom/gsd-input-helper.c index 47e9931a5..3653ef15d 100644 --- a/panels/wacom/gsd-input-helper.c +++ b/panels/wacom/gsd-input-helper.c @@ -289,6 +289,69 @@ out: return NULL; } +#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, *ptr; + int id; + + id = 0x0; + + gdk_display_sync (gdk_display_get_default ()); + + prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), WACOM_SERIAL_IDS_PROP, False); + if (!prop) + return id; + + 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 0x0; + } + + if (gdk_error_trap_pop ()) + goto out; + + if (nitems != 4) + goto out; + + if (act_type != XA_INTEGER) + goto out; + + if (act_format != 32) + 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) */ + ptr = data; + ptr += act_format/8 * 2; + + id = *((int32_t*)ptr); + id = id & 0xfffff; + + /* 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) diff --git a/panels/wacom/gsd-input-helper.h b/panels/wacom/gsd-input-helper.h index 0bc205b7c..3a774ea00 100644 --- a/panels/wacom/gsd-input-helper.h +++ b/panels/wacom/gsd-input-helper.h @@ -27,6 +27,8 @@ G_BEGIN_DECLS #include #include +#define WACOM_SERIAL_IDS_PROP "Wacom Serial IDs" + typedef enum { COMMAND_DEVICE_ADDED, COMMAND_DEVICE_REMOVED, @@ -69,8 +71,9 @@ gboolean device_set_property (XDevice *xdevice, gboolean run_custom_command (GdkDevice *device, CustomCommand command); -GList * get_disabled_devices (GdkDeviceManager *manager); -char * xdevice_get_device_node (int deviceid); +GList * get_disabled_devices (GdkDeviceManager *manager); +char * xdevice_get_device_node (int deviceid); +int xdevice_get_last_tool_id (int deviceid); G_END_DECLS diff --git a/panels/wacom/gsd-wacom-device.c b/panels/wacom/gsd-wacom-device.c index c523a1f4a..bddc4621f 100644 --- a/panels/wacom/gsd-wacom-device.c +++ b/panels/wacom/gsd-wacom-device.c @@ -30,6 +30,7 @@ #include #include +#include #include "gsd-input-helper.h" @@ -49,6 +50,7 @@ struct GsdWacomStylusPrivate { GsdWacomDevice *device; int id; + WacomStylusType type; char *name; const char *icon_name; GSettings *settings; @@ -131,7 +133,8 @@ gsd_wacom_stylus_new (GsdWacomDevice *device, stylus->priv->id = libwacom_stylus_get_id (wstylus); stylus->priv->name = g_strdup (libwacom_stylus_get_name (wstylus)); stylus->priv->settings = settings; - stylus->priv->icon_name = get_icon_name_from_type (libwacom_stylus_get_type (wstylus)); + stylus->priv->type = libwacom_stylus_get_type (wstylus); + stylus->priv->icon_name = get_icon_name_from_type (stylus->priv->type); return stylus; } @@ -181,6 +184,9 @@ gsd_wacom_stylus_get_device (GsdWacomStylus *stylus) struct GsdWacomDevicePrivate { GdkDevice *gdk_device; + int device_id; + int opcode; + GsdWacomDeviceType type; char *name; char *icon_name; @@ -204,6 +210,76 @@ static void gsd_wacom_device_finalize (GObject *object); G_DEFINE_TYPE (GsdWacomDevice, gsd_wacom_device, G_TYPE_OBJECT) +static GdkFilterReturn +filter_events (XEvent *xevent, + GdkEvent *event, + GsdWacomDevice *device) +{ + XIEvent *xiev; + XIPropertyEvent *pev; + XGenericEventCookie *cookie; + char *name; + int tool_id; + + /* verify we have a property event */ + if (xevent->type != GenericEvent) + return GDK_FILTER_CONTINUE; + + cookie = &xevent->xcookie; + if (cookie->extension != device->priv->opcode) + return GDK_FILTER_CONTINUE; + + xiev = (XIEvent *) xevent->xcookie.data; + + if (xiev->evtype != XI_PropertyEvent) + return GDK_FILTER_CONTINUE; + + pev = (XIPropertyEvent *) xiev; + + /* Is the event for us? */ + if (pev->deviceid != device->priv->device_id) + return GDK_FILTER_CONTINUE; + + name = XGetAtomName (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), pev->property); + if (name == NULL || + g_strcmp0 (name, WACOM_SERIAL_IDS_PROP) != 0) { + return GDK_FILTER_CONTINUE; + } + XFree (name); + + tool_id = xdevice_get_last_tool_id (device->priv->device_id); + gsd_wacom_device_set_current_stylus (device, tool_id); + + return GDK_FILTER_CONTINUE; +} + +static gboolean +setup_property_notify (GsdWacomDevice *device) +{ + Display *dpy; + XIEventMask evmask; + unsigned char bitmask[2] = { 0 }; + int tool_id; + + XISetMask (bitmask, XI_PropertyEvent); + + evmask.deviceid = device->priv->device_id; + evmask.mask_len = sizeof (bitmask); + evmask.mask = bitmask; + + dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); + XISelectEvents (dpy, DefaultRootWindow(dpy), &evmask, 1); + + gdk_window_add_filter (NULL, + (GdkFilterFunc) filter_events, + device); + + tool_id = xdevice_get_last_tool_id (device->priv->device_id); + gsd_wacom_device_set_current_stylus (device, tool_id); + + return TRUE; +} + static GsdWacomDeviceType get_device_type (XDeviceInfo *dev) { @@ -360,9 +436,10 @@ gsd_wacom_device_constructor (GType type, GObjectConstructParam *construct_properties) { GsdWacomDevice *device; + GdkDeviceManager *device_manager; XDeviceInfo *device_info; WacomDevice *wacom_device; - int n_devices, id; + int n_devices; guint i; char *path; @@ -373,7 +450,10 @@ gsd_wacom_device_constructor (GType type, if (device->priv->gdk_device == NULL) return G_OBJECT (device); - g_object_get (device->priv->gdk_device, "device-id", &id, NULL); + device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); + g_object_get (device_manager, "opcode", &device->priv->opcode, NULL); + + g_object_get (device->priv->gdk_device, "device-id", &device->priv->device_id, NULL); device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); if (device_info == NULL) { @@ -382,7 +462,7 @@ gsd_wacom_device_constructor (GType type, } for (i = 0; i < n_devices; i++) { - if (device_info[i].id == id) { + if (device_info[i].id == device->priv->device_id) { device->priv->type = get_device_type (&device_info[i]); device->priv->tool_name = g_strdup (device_info[i].name); break; @@ -394,9 +474,9 @@ gsd_wacom_device_constructor (GType type, if (device->priv->type == WACOM_TYPE_INVALID) goto end; - path = xdevice_get_device_node (id); + path = xdevice_get_device_node (device->priv->device_id); if (path == NULL) { - g_warning ("Could not get the device node path for ID '%d'", id); + g_warning ("Could not get the device node path for ID '%d'", device->priv->device_id); device->priv->type = WACOM_TYPE_INVALID; goto end; } @@ -430,6 +510,11 @@ gsd_wacom_device_constructor (GType type, libwacom_destroy (wacom_device); g_free (path); + if (device->priv->type == WACOM_TYPE_STYLUS || + device->priv->type == WACOM_TYPE_ERASER) { + setup_property_notify (device); + } + end: return G_OBJECT (device); } @@ -536,6 +621,10 @@ gsd_wacom_device_finalize (GObject *object) g_free (p->icon_name); p->icon_name = NULL; + gdk_window_remove_filter (NULL, + (GdkFilterFunc) filter_events, + device); + G_OBJECT_CLASS (gsd_wacom_device_parent_class)->finalize (object); } @@ -603,6 +692,40 @@ gsd_wacom_device_get_settings (GsdWacomDevice *device) return device->priv->wacom_settings; } +void +gsd_wacom_device_set_current_stylus (GsdWacomDevice *device, + int stylus_id) +{ + GList *l; + + g_return_if_fail (GSD_IS_WACOM_DEVICE (device)); + + /* Don't change anything if the stylus is already set */ + if (device->priv->last_stylus != NULL) { + GsdWacomStylus *stylus = device->priv->last_stylus; + if (stylus->priv->id == stylus_id) + return; + } + + for (l = device->priv->styli; l; l = l->next) { + GsdWacomStylus *stylus = l->data; + + /* Set a nice default if 0x0 */ + if (stylus_id == 0x0 && + stylus->priv->type == WSTYLUS_GENERAL) { + g_object_set (device, "last-stylus", stylus, NULL); + return; + } + + if (stylus->priv->id == stylus_id) { + g_object_set (device, "last-stylus", stylus, NULL); + return; + } + } + + g_warning ("Could not find stylus ID 0x%x for tablet '%s'", stylus_id, device->priv->name); +} + GsdWacomDeviceType gsd_wacom_device_get_device_type (GsdWacomDevice *device) { diff --git a/panels/wacom/gsd-wacom-device.h b/panels/wacom/gsd-wacom-device.h index ecea0ae28..235e75a57 100644 --- a/panels/wacom/gsd-wacom-device.h +++ b/panels/wacom/gsd-wacom-device.h @@ -92,6 +92,8 @@ const char * gsd_wacom_device_get_tool_name (GsdWacomDevice *device); gboolean gsd_wacom_device_reversible (GsdWacomDevice *device); gboolean gsd_wacom_device_is_screen_tablet (GsdWacomDevice *device); GSettings * gsd_wacom_device_get_settings (GsdWacomDevice *device); +void gsd_wacom_device_set_current_stylus (GsdWacomDevice *device, + int stylus_id); GsdWacomDeviceType gsd_wacom_device_get_device_type (GsdWacomDevice *device); const char * gsd_wacom_device_type_to_string (GsdWacomDeviceType type);