[mutter] clutter/x11: Implement ClutterInputDeviceTool



commit ea4dbdd66f11f40b612fac392ce5972464215a8f
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Oct 31 18:05:23 2016 +0100

    clutter/x11: Implement ClutterInputDeviceTool
    
    This is implemented using Wacom-driver specific properties at
    the moment, until libinput becomes the fallback driver handling
    tablet and pad management.
    
    Whenever a tool becomes in proximity, a new ClutterInputDeviceToolXI2
    will be created (if it wasn't created previously) for the given
    serial number. This tool will be set in all events send from the
    device.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773779

 clutter/clutter/Makefile.am                        |    2 +
 clutter/clutter/x11/clutter-device-manager-xi2.c   |   87 +++++++++++++++++++-
 clutter/clutter/x11/clutter-device-manager-xi2.h   |    1 +
 .../clutter/x11/clutter-input-device-tool-xi2.c    |   51 ++++++++++++
 .../clutter/x11/clutter-input-device-tool-xi2.h    |   74 +++++++++++++++++
 clutter/clutter/x11/clutter-input-device-xi2.c     |   16 ++++
 clutter/clutter/x11/clutter-input-device-xi2.h     |    3 +
 7 files changed, 233 insertions(+), 1 deletions(-)
---
diff --git a/clutter/clutter/Makefile.am b/clutter/clutter/Makefile.am
index 2f7e6c3..8b1d54e 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 62a12c4..8bddebf 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 2ceb623..c8e66f9 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 0000000..396b847
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#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 0000000..1878b9d
--- /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 <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__
+#define __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__
+
+#include <clutter/clutter-input-device-tool.h>
+
+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 00416a3..d6bb87f 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 92dadc9..b93684f 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
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]