[mutter/wip/carlosg/capabilities-and-dimensions: 3/11] backends/x11: Set trackball/trackpoint capabilities




commit fdfbfc68c99c3cd3b942fb7710b95dbe3fa3a311
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Sep 6 09:48:09 2022 +0200

    backends/x11: Set trackball/trackpoint capabilities
    
    Use gudev to detect these capabilities in input devices.

 src/backends/x11/meta-seat-x11.c | 133 +++++++++++++++++++++++++++++++++------
 1 file changed, 114 insertions(+), 19 deletions(-)
---
diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
index e972c80c65..e99a4a871e 100644
--- a/src/backends/x11/meta-seat-x11.c
+++ b/src/backends/x11/meta-seat-x11.c
@@ -22,6 +22,10 @@
 #include <X11/extensions/XInput2.h>
 #include <X11/extensions/XKB.h>
 
+#ifdef HAVE_LIBGUDEV
+#include <gudev/gudev.h>
+#endif
+
 #include "backends/meta-input-settings-private.h"
 #include "backends/x11/meta-backend-x11.h"
 #include "backends/x11/meta-clutter-backend-x11.h"
@@ -72,6 +76,10 @@ struct _MetaSeatX11
   GHashTable *touch_coords;
   MetaKeymapX11 *keymap;
 
+#ifdef HAVE_LIBGUDEV
+  GUdevClient *udev_client;
+#endif
+
   int pointer_id;
   int keyboard_id;
   int opcode;
@@ -234,10 +242,11 @@ translate_device_classes (Display             *xdisplay,
 }
 
 static gboolean
-is_touch_device (XIAnyClassInfo         **classes,
-                 int                      n_classes,
-                 ClutterInputDeviceType  *device_type,
-                 uint32_t                *n_touch_points)
+is_touch_device (XIAnyClassInfo           **classes,
+                 int                        n_classes,
+                 ClutterInputDeviceType    *device_type,
+                 ClutterInputCapabilities  *capabilities,
+                 uint32_t                  *n_touch_points)
 {
   int i;
 
@@ -251,11 +260,21 @@ is_touch_device (XIAnyClassInfo         **classes,
       if (class->num_touches > 0)
         {
           if (class->mode == XIDirectTouch)
-            *device_type = CLUTTER_TOUCHSCREEN_DEVICE;
+            {
+              *device_type = CLUTTER_TOUCHSCREEN_DEVICE;
+              *capabilities = CLUTTER_INPUT_CAPABILITY_TOUCH;
+            }
           else if (class->mode == XIDependentTouch)
-            *device_type = CLUTTER_TOUCHPAD_DEVICE;
+            {
+              *device_type = CLUTTER_TOUCHPAD_DEVICE;
+              *capabilities =
+                CLUTTER_INPUT_CAPABILITY_POINTER |
+                CLUTTER_INPUT_CAPABILITY_TOUCHPAD;
+            }
           else
-            continue;
+            {
+              continue;
+            }
 
           *n_touch_points = class->num_touches;
 
@@ -405,9 +424,10 @@ get_pad_features (XIDeviceInfo *info,
 /* The Wacom driver exports the tool type as property. Use that over
    guessing based on the device name */
 static gboolean
-guess_source_from_wacom_type (MetaSeatX11             *seat_x11,
-                              XIDeviceInfo            *info,
-                              ClutterInputDeviceType  *source_out)
+guess_source_from_wacom_type (MetaSeatX11              *seat_x11,
+                              XIDeviceInfo             *info,
+                              ClutterInputDeviceType   *source_out,
+                              ClutterInputCapabilities *capabilities_out)
 {
   Display *xdisplay = xdisplay_from_seat (seat_x11);
   gulong nitems, bytes_after;
@@ -453,26 +473,33 @@ guess_source_from_wacom_type (MetaSeatX11             *seat_x11,
   if (device_type == types[WACOM_TYPE_STYLUS])
     {
       *source_out = CLUTTER_PEN_DEVICE;
+      *capabilities_out = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
     }
   else if (device_type == types[WACOM_TYPE_CURSOR])
     {
       *source_out = CLUTTER_CURSOR_DEVICE;
+      *capabilities_out = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
     }
   else if (device_type == types[WACOM_TYPE_ERASER])
     {
       *source_out = CLUTTER_ERASER_DEVICE;
+      *capabilities_out = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
     }
   else if (device_type == types[WACOM_TYPE_PAD])
     {
       *source_out = CLUTTER_PAD_DEVICE;
+      *capabilities_out = CLUTTER_INPUT_CAPABILITY_TABLET_PAD;
     }
   else if (device_type == types[WACOM_TYPE_TOUCH])
     {
         uint32_t num_touches = 0;
 
         if (!is_touch_device (info->classes, info->num_classes,
-                              source_out, &num_touches))
+                              source_out, capabilities_out, &num_touches))
+          {
             *source_out = CLUTTER_TOUCHSCREEN_DEVICE;
+            *capabilities_out = CLUTTER_INPUT_CAPABILITY_TOUCH;
+          }
     }
   else
     {
@@ -482,6 +509,25 @@ guess_source_from_wacom_type (MetaSeatX11             *seat_x11,
   return TRUE;
 }
 
+#ifdef HAVE_LIBGUDEV
+static gboolean
+has_udev_property (GUdevDevice *udev_device,
+                   const char  *property_name)
+{
+  g_autoptr (GUdevDevice) parent_udev_device = NULL;
+
+  if (NULL != g_udev_device_get_property (udev_device, property_name))
+    return TRUE;
+
+  parent_udev_device = g_udev_device_get_parent (udev_device);
+
+  if (!parent_udev_device)
+    return FALSE;
+
+  return g_udev_device_get_property (parent_udev_device, property_name) != NULL;
+}
+#endif
+
 static ClutterInputDevice *
 create_device (MetaSeatX11    *seat_x11,
                ClutterBackend *clutter_backend,
@@ -489,6 +535,7 @@ create_device (MetaSeatX11    *seat_x11,
 {
   Display *xdisplay = xdisplay_from_seat (seat_x11);
   ClutterInputDeviceType source, touch_source;
+  ClutterInputCapabilities capabilities = 0;
   ClutterInputDevice *retval;
   ClutterInputMode mode;
   uint32_t num_touches = 0, num_rings = 0, num_strips = 0;
@@ -497,6 +544,7 @@ create_device (MetaSeatX11    *seat_x11,
   if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
     {
       source = CLUTTER_KEYBOARD_DEVICE;
+      capabilities = CLUTTER_INPUT_CAPABILITY_KEYBOARD;
     }
   else if (is_touchpad_device (seat_x11, info))
     {
@@ -504,29 +552,49 @@ create_device (MetaSeatX11    *seat_x11,
     }
   else if (info->use == XISlavePointer &&
            is_touch_device (info->classes, info->num_classes,
-                            &touch_source,
+                            &touch_source, &capabilities,
                             &num_touches))
     {
       source = touch_source;
     }
-  else if (!guess_source_from_wacom_type (seat_x11, info, &source))
+  else if (!guess_source_from_wacom_type (seat_x11, info, &source, &capabilities))
     {
       char *name;
 
       name = g_ascii_strdown (info->name, -1);
 
       if (strstr (name, "eraser") != NULL)
-        source = CLUTTER_ERASER_DEVICE;
+        {
+          source = CLUTTER_ERASER_DEVICE;
+          capabilities = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
+        }
       else if (strstr (name, "cursor") != NULL)
-        source = CLUTTER_CURSOR_DEVICE;
+        {
+          source = CLUTTER_CURSOR_DEVICE;
+          capabilities = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
+        }
       else if (strstr (name, " pad") != NULL)
-        source = CLUTTER_PAD_DEVICE;
+        {
+          source = CLUTTER_PAD_DEVICE;
+          capabilities = CLUTTER_INPUT_CAPABILITY_TABLET_PAD;
+        }
       else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
-        source = CLUTTER_PEN_DEVICE;
+        {
+          source = CLUTTER_PEN_DEVICE;
+          capabilities = CLUTTER_INPUT_CAPABILITY_TABLET_TOOL;
+        }
       else if (strstr (name, "touchpad") != NULL)
-        source = CLUTTER_TOUCHPAD_DEVICE;
+        {
+          source = CLUTTER_TOUCHPAD_DEVICE;
+          capabilities =
+            CLUTTER_INPUT_CAPABILITY_POINTER |
+            CLUTTER_INPUT_CAPABILITY_TOUCHPAD;
+        }
       else
-        source = CLUTTER_POINTER_DEVICE;
+        {
+          source = CLUTTER_POINTER_DEVICE;
+          capabilities = CLUTTER_INPUT_CAPABILITY_POINTER;
+        }
 
       g_free (name);
     }
@@ -556,6 +624,23 @@ create_device (MetaSeatX11    *seat_x11,
       node_path = get_device_node_path (seat_x11, info);
     }
 
+#ifdef HAVE_LIBGUDEV
+  if (node_path)
+    {
+      g_autoptr (GUdevDevice) udev_device = NULL;
+
+      udev_device = g_udev_client_query_by_device_file (seat_x11->udev_client,
+                                                        node_path);
+      if (udev_device)
+        {
+          if (has_udev_property (udev_device, "ID_INPUT_TRACKBALL"))
+            capabilities |= CLUTTER_INPUT_CAPABILITY_TRACKBALL;
+          if (has_udev_property (udev_device, "ID_INPUT_POINTINGSTICK"))
+            capabilities |= CLUTTER_INPUT_CAPABILITY_TRACKPOINT;
+        }
+    }
+#endif
+
   if (source == CLUTTER_PAD_DEVICE)
     get_pad_features (info, &num_rings, &num_strips);
 
@@ -564,6 +649,7 @@ create_device (MetaSeatX11    *seat_x11,
                          "id", info->deviceid,
                          "has-cursor", (info->use == XIMasterPointer),
                          "device-type", source,
+                         "capabilities", capabilities,
                          "device-mode", mode,
                          "backend", clutter_backend,
                          "vendor-id", vendor_id,
@@ -1410,6 +1496,11 @@ meta_seat_x11_constructed (GObject *object)
   XIEventMask event_mask;
   unsigned char mask[XIMaskLen(XI_LASTEVENT)] = { 0, };
   int n_devices, i;
+#ifdef HAVE_LIBGUDEV
+  const char *udev_subsystems[] = { "input", NULL };
+
+  seat_x11->udev_client = g_udev_client_new (udev_subsystems);
+#endif
 
   info = XIQueryDevice (xdisplay, XIAllDevices, &n_devices);
 
@@ -1475,6 +1566,10 @@ meta_seat_x11_finalize (GObject *object)
 {
   MetaSeatX11 *seat_x11 = META_SEAT_X11 (object);
 
+#ifdef HAVE_LIBGUDEV
+  g_clear_object (&seat_x11->udev_client);
+#endif
+
   g_hash_table_unref (seat_x11->devices_by_id);
   g_hash_table_unref (seat_x11->tools_by_serial);
   g_hash_table_unref (seat_x11->touch_coords);


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