diff --git a/clutter/clutter/Makefile.am b/clutter/clutter/Makefile.am index 2f7e6c372..8b1d54ecd 100644 --- a/clutter/clutter/Makefile.am +++ b/clutter/clutter/Makefile.am @@ -413,11 +413,13 @@ x11_source_c_priv = \ x11_source_c += \ x11/clutter-device-manager-xi2.c \ x11/clutter-input-device-xi2.c \ + x11/clutter-input-device-tool-xi2.c \ $(NULL) x11_source_h_priv += \ x11/clutter-device-manager-xi2.h \ x11/clutter-input-device-xi2.h \ + x11/clutter-input-device-tool-xi2.h \ $(NULL) x11_source_c += \ diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c index 62a12c40c..8bddebf1d 100644 --- a/clutter/clutter/x11/clutter-device-manager-xi2.c +++ b/clutter/clutter/x11/clutter-device-manager-xi2.c @@ -29,6 +29,7 @@ #include "clutter-backend-x11.h" #include "clutter-input-device-xi2.h" +#include "clutter-input-device-tool-xi2.h" #include "clutter-virtual-input-device-x11.h" #include "clutter-stage-x11.h" @@ -952,6 +953,78 @@ clutter_device_manager_xi2_select_stage_events (ClutterDeviceManager *manager, g_free (mask); } +static guint +device_get_tool_serial (ClutterBackendX11 *backend_x11, + ClutterInputDevice *device) +{ + gulong nitems, bytes_after; + guint32 *data = NULL; + guint serial_id = 0; + int rc, format; + Atom type; + Atom prop; + + prop = XInternAtom (backend_x11->xdpy, "Wacom Serial IDs", True); + if (prop == None) + return 0; + + clutter_x11_trap_x_errors (); + rc = XIGetProperty (backend_x11->xdpy, + clutter_input_device_get_device_id (device), + prop, 0, 4, FALSE, XA_INTEGER, &type, &format, &nitems, &bytes_after, + (guchar **) &data); + clutter_x11_untrap_x_errors (); + + if (rc == Success && type == XA_INTEGER && format == 32 && nitems >= 4) + serial_id = data[3]; + + XFree (data); + + return serial_id; +} + +static void +handle_property_event (ClutterDeviceManagerXI2 *manager_xi2, + XIEvent *event) +{ + XIPropertyEvent *xev = (XIPropertyEvent *) event; + ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ()); + Atom serial_ids_prop = XInternAtom (backend_x11->xdpy, "Wacom Serial IDs", True); + ClutterInputDevice *device; + + device = g_hash_table_lookup (manager_xi2->devices_by_id, + GINT_TO_POINTER (xev->deviceid)); + if (!device) + return; + + if (xev->property == serial_ids_prop) + { + ClutterInputDeviceTool *tool = NULL; + ClutterInputDeviceToolType type; + guint serial_id; + + serial_id = device_get_tool_serial (backend_x11, device); + + if (serial_id != 0) + { + tool = g_hash_table_lookup (manager_xi2->tools_by_serial, + GUINT_TO_POINTER (serial_id)); + if (!tool) + { + type = clutter_input_device_get_device_type (device) == CLUTTER_ERASER_DEVICE ? + CLUTTER_INPUT_DEVICE_TOOL_ERASER : CLUTTER_INPUT_DEVICE_TOOL_PEN; + tool = clutter_input_device_tool_xi2_new (serial_id, type); + g_hash_table_insert (manager_xi2->tools_by_serial, + GUINT_TO_POINTER (serial_id), + tool); + } + } + + clutter_input_device_xi2_update_tool (device, tool); + g_signal_emit_by_name (manager_xi2, "tool-changed", device, tool); + } +} + static ClutterTranslateReturn clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, gpointer native, @@ -983,7 +1056,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, return CLUTTER_TRANSLATE_REMOVE; if (!(xi_event->evtype == XI_HierarchyChanged || - xi_event->evtype == XI_DeviceChanged)) + xi_event->evtype == XI_DeviceChanged || + xi_event->evtype == XI_PropertyEvent)) { stage = get_event_stage (translator, xi_event); if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) @@ -1247,6 +1321,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, clutter_event_set_source_device (event, source_device); clutter_event_set_device (event, device); + clutter_event_set_device_tool (event, + clutter_input_device_xi2_get_current_tool (source_device)); event->button.axes = translate_axes (event->button.device, event->button.x, @@ -1355,6 +1431,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, clutter_event_set_source_device (event, source_device); clutter_event_set_device (event, device); + clutter_event_set_device_tool (event, + clutter_input_device_xi2_get_current_tool (source_device)); event->motion.axes = translate_axes (event->motion.device, event->motion.x, @@ -1556,6 +1634,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, case XI_FocusOut: retval = CLUTTER_TRANSLATE_CONTINUE; break; + case XI_PropertyEvent: + handle_property_event (manager_xi2, xi_event); + retval = CLUTTER_TRANSLATE_CONTINUE; + break; } return retval; @@ -1733,6 +1815,7 @@ clutter_device_manager_xi2_constructed (GObject *gobject) XISetMask (mask, XI_HierarchyChanged); XISetMask (mask, XI_DeviceChanged); + XISetMask (mask, XI_PropertyEvent); event_mask.deviceid = XIAllDevices; event_mask.mask_len = sizeof (mask); @@ -1814,4 +1897,6 @@ clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self) self->devices_by_id = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref); + self->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_object_unref); } diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.h b/clutter/clutter/x11/clutter-device-manager-xi2.h index 2ceb623a6..c8e66f949 100644 --- a/clutter/clutter/x11/clutter-device-manager-xi2.h +++ b/clutter/clutter/x11/clutter-device-manager-xi2.h @@ -43,6 +43,7 @@ struct _ClutterDeviceManagerXI2 ClutterDeviceManager parent_instance; GHashTable *devices_by_id; + GHashTable *tools_by_serial; GSList *all_devices; diff --git a/clutter/clutter/x11/clutter-input-device-tool-xi2.c b/clutter/clutter/x11/clutter-input-device-tool-xi2.c new file mode 100644 index 000000000..396b84736 --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-tool-xi2.c @@ -0,0 +1,51 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2016 Red Hat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Carlos Garnacho + */ + +#ifdef HAVE_CONFIG_H +#include "clutter-build-config.h" +#endif + +#include "clutter-input-device-tool-xi2.h" + +G_DEFINE_TYPE (ClutterInputDeviceToolXI2, clutter_input_device_tool_xi2, + CLUTTER_TYPE_INPUT_DEVICE_TOOL) + +static void +clutter_input_device_tool_xi2_class_init (ClutterInputDeviceToolXI2Class *klass) +{ +} + +static void +clutter_input_device_tool_xi2_init (ClutterInputDeviceToolXI2 *tool) +{ +} + +ClutterInputDeviceTool * +clutter_input_device_tool_xi2_new (guint serial, + ClutterInputDeviceToolType type) +{ + return g_object_new (CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, + "type", type, + "serial", serial, + NULL); +} diff --git a/clutter/clutter/x11/clutter-input-device-tool-xi2.h b/clutter/clutter/x11/clutter-input-device-tool-xi2.h new file mode 100644 index 000000000..1878b9def --- /dev/null +++ b/clutter/clutter/x11/clutter-input-device-tool-xi2.h @@ -0,0 +1,74 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright © 2016 Red Hat + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Carlos Garnacho + */ + +#ifndef __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__ +#define __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2 (clutter_input_device_tool_xi2_get_type ()) + +#define CLUTTER_INPUT_DEVICE_TOOL_XI2(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2)) + +#define CLUTTER_IS_INPUT_DEVICE_TOOL_XI2(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2)) + +#define CLUTTER_INPUT_DEVICE_TOOL_XI2_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2Class)) + +#define CLUTTER_IS_INPUT_DEVICE_TOOL_XI2_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2)) + +#define CLUTTER_INPUT_DEVICE_TOOL_XI2_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), \ + CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2Class)) + +typedef struct _ClutterInputDeviceToolXI2 ClutterInputDeviceToolXI2; +typedef struct _ClutterInputDeviceToolXI2Class ClutterInputDeviceToolXI2Class; + +struct _ClutterInputDeviceToolXI2 +{ + ClutterInputDeviceTool parent_instance; + struct libinput_tablet_tool *tool; +}; + +struct _ClutterInputDeviceToolXI2Class +{ + ClutterInputDeviceToolClass parent_class; +}; + +GType clutter_input_device_xi2_evdev_get_type (void) G_GNUC_CONST; + +ClutterInputDeviceTool * clutter_input_device_tool_xi2_new (guint serial, + ClutterInputDeviceToolType type); + +G_END_DECLS + +#endif /* __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__ */ diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c index 00416a33c..d6bb87fdf 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.c +++ b/clutter/clutter/x11/clutter-input-device-xi2.c @@ -44,6 +44,7 @@ struct _ClutterInputDeviceXI2 ClutterInputDevice device; gint device_id; + ClutterInputDeviceTool *current_tool; }; #define N_BUTTONS 5 @@ -172,3 +173,18 @@ _clutter_input_device_xi2_translate_state (ClutterEvent *event, _clutter_event_set_state_full (event, button, base, latched, locked, effective); } + +void +clutter_input_device_xi2_update_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + g_set_object (&device_xi2->current_tool, tool); +} + +ClutterInputDeviceTool * +clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + return device_xi2->current_tool; +} diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h index 92dadc965..b93684f71 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.h +++ b/clutter/clutter/x11/clutter-input-device-xi2.h @@ -41,6 +41,9 @@ void _clutter_input_device_xi2_translate_state (ClutterEvent *event, XIModifierState *modifiers_state, XIButtonState *buttons_state, XIGroupState *group_state); +void clutter_input_device_xi2_update_tool (ClutterInputDevice *device, + ClutterInputDeviceTool *tool); +ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device); G_END_DECLS