[mutter] clutter/evdev: Don't treat device touch slots as seat slots



commit b6477a826d37cebc96ae41e86a555212ca4411ec
Author: Jonas Ådahl <jadahl gmail com>
Date:   Sat Jan 27 00:25:56 2018 +0800

    clutter/evdev: Don't treat device touch slots as seat slots
    
    IF two touch devices have colliding touch point IDs they'd interfere on
    the seat. To avoid this, always allocate a seat wide slot for each
    device wide slot, but don't use device slots directly in the seat.

 .../clutter/evdev/clutter-device-manager-evdev.c   | 48 ++++++++--------
 clutter/clutter/evdev/clutter-input-device-evdev.c | 65 ++++++++++++++++++++++
 clutter/clutter/evdev/clutter-input-device-evdev.h | 15 +++++
 clutter/clutter/evdev/clutter-seat-evdev.c         | 64 ++++++++++++++-------
 clutter/clutter/evdev/clutter-seat-evdev.h         | 16 ++++--
 5 files changed, 155 insertions(+), 53 deletions(-)
---
diff --git a/clutter/clutter/evdev/clutter-device-manager-evdev.c 
b/clutter/clutter/evdev/clutter-device-manager-evdev.c
index 6a9a1fc11..161c90524 100644
--- a/clutter/clutter/evdev/clutter-device-manager-evdev.c
+++ b/clutter/clutter/evdev/clutter-device-manager-evdev.c
@@ -1361,7 +1361,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
 
     case LIBINPUT_EVENT_TOUCH_DOWN:
       {
-        gint32 slot;
+        int device_slot;
         guint64 time_us;
         double x, y;
         gfloat stage_width, stage_height;
@@ -1382,21 +1382,23 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
 
-        slot = libinput_event_touch_get_slot (touch_event);
+        device_slot = libinput_event_touch_get_slot (touch_event);
         time_us = libinput_event_touch_get_time_usec (touch_event);
         x = libinput_event_touch_get_x_transformed (touch_event,
                                                     stage_width);
         y = libinput_event_touch_get_y_transformed (touch_event,
                                                     stage_height);
 
-        touch_state = clutter_seat_evdev_add_touch (seat, slot);
+        touch_state =
+          clutter_input_device_evdev_acquire_touch_state (device_evdev,
+                                                          device_slot);
         touch_state->coords.x = x;
         touch_state->coords.y = y;
 
         clutter_seat_evdev_notify_touch_event (seat, device,
                                                CLUTTER_TOUCH_BEGIN,
                                                time_us,
-                                               slot,
+                                               touch_state->seat_slot,
                                                touch_state->coords.x,
                                                touch_state->coords.y);
         break;
@@ -1404,7 +1406,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
 
     case LIBINPUT_EVENT_TOUCH_UP:
       {
-        gint32 slot;
+        int device_slot;
         guint64 time_us;
         ClutterSeatEvdev *seat;
         ClutterTouchState *touch_state;
@@ -1415,24 +1417,27 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
         device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
         seat = _clutter_input_device_evdev_get_seat (device_evdev);
 
-        slot = libinput_event_touch_get_slot (touch_event);
+        device_slot = libinput_event_touch_get_slot (touch_event);
         time_us = libinput_event_touch_get_time_usec (touch_event);
-        touch_state = clutter_seat_evdev_get_touch (seat, slot);
+        touch_state =
+          clutter_input_device_evdev_lookup_touch_state (device_evdev,
+                                                         device_slot);
         if (!touch_state)
           break;
 
         clutter_seat_evdev_notify_touch_event (seat, device,
                                                CLUTTER_TOUCH_END, time_us,
-                                               slot,
+                                               touch_state->seat_slot,
                                                touch_state->coords.x,
                                                touch_state->coords.y);
-        clutter_seat_evdev_remove_touch (seat, slot);
+        clutter_input_device_evdev_release_touch_state (device_evdev,
+                                                        touch_state);
         break;
       }
 
     case LIBINPUT_EVENT_TOUCH_MOTION:
       {
-        gint32 slot;
+        int device_slot;
         guint64 time_us;
         double x, y;
         gfloat stage_width, stage_height;
@@ -1453,14 +1458,16 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
         stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
         stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
 
-        slot = libinput_event_touch_get_slot (touch_event);
+        device_slot = libinput_event_touch_get_slot (touch_event);
         time_us = libinput_event_touch_get_time_usec (touch_event);
         x = libinput_event_touch_get_x_transformed (touch_event,
                                                     stage_width);
         y = libinput_event_touch_get_y_transformed (touch_event,
                                                     stage_height);
 
-        touch_state = clutter_seat_evdev_get_touch (seat, slot);
+        touch_state =
+          clutter_input_device_evdev_lookup_touch_state (device_evdev,
+                                                         device_slot);
         if (!touch_state)
           break;
 
@@ -1470,33 +1477,22 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
         clutter_seat_evdev_notify_touch_event (seat, device,
                                                CLUTTER_TOUCH_UPDATE,
                                                time_us,
-                                               slot,
+                                               touch_state->seat_slot,
                                                touch_state->coords.x,
                                                touch_state->coords.y);
         break;
       }
     case LIBINPUT_EVENT_TOUCH_CANCEL:
       {
-        ClutterTouchState *touch_state;
-        GHashTableIter iter;
         guint64 time_us;
         struct libinput_event_touch *touch_event =
           libinput_event_get_touch_event (event);
-        ClutterSeatEvdev *seat;
 
         device = libinput_device_get_user_data (libinput_device);
+        device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
         time_us = libinput_event_touch_get_time_usec (touch_event);
-        seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device));
-        g_hash_table_iter_init (&iter, seat->touches);
 
-        while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_state))
-          {
-            clutter_seat_evdev_notify_touch_event (seat, device, CLUTTER_TOUCH_CANCEL,
-                                                   time_us, touch_state->id,
-                                                   touch_state->coords.x,
-                                                   touch_state->coords.y);
-            g_hash_table_iter_remove (&iter);
-          }
+        clutter_input_device_evdev_release_touch_slots (device_evdev, time_us);
 
         break;
       }
diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.c 
b/clutter/clutter/evdev/clutter-input-device-evdev.c
index f275f1c42..322f5224e 100644
--- a/clutter/clutter/evdev/clutter-input-device-evdev.c
+++ b/clutter/clutter/evdev/clutter-input-device-evdev.c
@@ -81,6 +81,9 @@ clutter_input_device_evdev_finalize (GObject *object)
   if (device_evdev->libinput_device)
     libinput_device_unref (device_evdev->libinput_device);
 
+  clutter_input_device_evdev_release_touch_slots (device_evdev,
+                                                  g_get_monotonic_time ());
+
   _clutter_device_manager_evdev_release_device_id (manager_evdev, device);
 
   clear_slow_keys (device_evdev);
@@ -1215,6 +1218,44 @@ clutter_input_device_evdev_apply_kbd_a11y_settings (ClutterInputDeviceEvdev *dev
   device->a11y_flags = settings->controls;
 }
 
+static void
+release_device_touch_slot (gpointer value)
+{
+  ClutterTouchState *touch_state = value;
+
+  clutter_seat_evdev_release_touch_state (touch_state->seat, touch_state);
+}
+
+ClutterTouchState *
+clutter_input_device_evdev_acquire_touch_state (ClutterInputDeviceEvdev *device,
+                                                int                      device_slot)
+{
+  ClutterTouchState *touch_state;
+
+  touch_state = clutter_seat_evdev_acquire_touch_state (device->seat,
+                                                        device_slot);
+  g_hash_table_insert (device->touches,
+                       GINT_TO_POINTER (device_slot),
+                       touch_state);
+
+  return touch_state;
+}
+
+ClutterTouchState *
+clutter_input_device_evdev_lookup_touch_state (ClutterInputDeviceEvdev *device,
+                                               int                      device_slot)
+{
+  return g_hash_table_lookup (device->touches, GINT_TO_POINTER (device_slot));
+}
+
+void
+clutter_input_device_evdev_release_touch_state (ClutterInputDeviceEvdev *device,
+                                                ClutterTouchState       *touch_state)
+{
+  g_hash_table_remove (device->touches,
+                       GINT_TO_POINTER (touch_state->device_slot));
+}
+
 static void
 clutter_input_device_evdev_class_init (ClutterInputDeviceEvdevClass *klass)
 {
@@ -1253,6 +1294,9 @@ clutter_input_device_evdev_init (ClutterInputDeviceEvdev *self)
   cairo_matrix_init_identity (&self->device_matrix);
   self->device_aspect_ratio = 0;
   self->output_ratio = 0;
+
+  self->touches = g_hash_table_new_full (NULL, NULL,
+                                         NULL, release_device_touch_slot);
 }
 
 /*
@@ -1486,3 +1530,24 @@ clutter_input_device_evdev_translate_coordinates (ClutterInputDevice *device,
   *x = CLAMP (x_d, MIN (min_x, max_x), MAX (min_x, max_x)) * stage_width;
   *y = CLAMP (y_d, MIN (min_y, max_y), MAX (min_y, max_y)) * stage_height;
 }
+
+void
+clutter_input_device_evdev_release_touch_slots (ClutterInputDeviceEvdev *device_evdev,
+                                                uint64_t                 time_us)
+{
+  GHashTableIter iter;
+  ClutterTouchState *touch_state;
+
+  g_hash_table_iter_init (&iter, device_evdev->touches);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &touch_state))
+    {
+      clutter_seat_evdev_notify_touch_event (touch_state->seat,
+                                             CLUTTER_INPUT_DEVICE (device_evdev),
+                                             CLUTTER_TOUCH_CANCEL,
+                                             time_us,
+                                             touch_state->seat_slot,
+                                             touch_state->coords.x,
+                                             touch_state->coords.y);
+      g_hash_table_iter_remove (&iter);
+    }
+}
diff --git a/clutter/clutter/evdev/clutter-input-device-evdev.h 
b/clutter/clutter/evdev/clutter-input-device-evdev.h
index 3c5b6e340..90463ee14 100644
--- a/clutter/clutter/evdev/clutter-input-device-evdev.h
+++ b/clutter/clutter/evdev/clutter-input-device-evdev.h
@@ -71,6 +71,8 @@ struct _ClutterInputDeviceEvdev
   gdouble device_aspect_ratio; /* w:h */
   gdouble output_ratio;        /* w:h */
 
+  GHashTable *touches;
+
   /* Keyboard a11y */
   ClutterKeyboardA11yFlags a11y_flags;
   GList *slow_keys_list;
@@ -137,6 +139,19 @@ void                      clutter_input_device_evdev_translate_coordinates (Clut
 void                      clutter_input_device_evdev_apply_kbd_a11y_settings (ClutterInputDeviceEvdev 
*device,
                                                                               ClutterKbdA11ySettings  
*settings);
 
+ClutterTouchState *       clutter_input_device_evdev_acquire_touch_state (ClutterInputDeviceEvdev *device,
+                                                                          int                      
device_slot);
+
+ClutterTouchState *       clutter_input_device_evdev_lookup_touch_state (ClutterInputDeviceEvdev *device,
+                                                                         int                      
device_slot);
+
+void                      clutter_input_device_evdev_release_touch_state (ClutterInputDeviceEvdev *device,
+                                                                          ClutterTouchState       
*touch_state);
+
+void                      clutter_input_device_evdev_release_touch_slots (ClutterInputDeviceEvdev 
*device_evdev,
+                                                                          uint64_t                 time_us);
+
+
 G_END_DECLS
 
 #endif /* __CLUTTER_INPUT_DEVICE_EVDEV_H__ */
diff --git a/clutter/clutter/evdev/clutter-seat-evdev.c b/clutter/clutter/evdev/clutter-seat-evdev.c
index 97648667b..e91f3673b 100644
--- a/clutter/clutter/evdev/clutter-seat-evdev.c
+++ b/clutter/clutter/evdev/clutter-seat-evdev.c
@@ -92,32 +92,57 @@ clutter_touch_state_free (ClutterTouchState *touch_state)
   g_slice_free (ClutterTouchState, touch_state);
 }
 
+static void
+ensure_seat_slot_allocated (ClutterSeatEvdev *seat,
+                            int               seat_slot)
+{
+  if (seat_slot >= seat->n_alloc_touch_states)
+    {
+      const int size_increase = 5;
+      int i;
+
+      seat->n_alloc_touch_states += size_increase;
+      seat->touch_states = g_realloc_n (seat->touch_states,
+                                        seat->n_alloc_touch_states,
+                                        sizeof (ClutterTouchState *));
+      for (i = 0; i < size_increase; i++)
+        seat->touch_states[seat->n_alloc_touch_states - (i + 1)] = NULL;
+    }
+}
+
 ClutterTouchState *
-clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat,
-                              guint32           id)
+clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat,
+                                        int               device_slot)
 {
-  ClutterTouchState *touch;
+  ClutterTouchState *touch_state;
+  int seat_slot;
 
-  touch = g_slice_new0 (ClutterTouchState);
-  touch->id = id;
+  for (seat_slot = 0; seat_slot < seat->n_alloc_touch_states; seat_slot++)
+    {
+      if (!seat->touch_states[seat_slot])
+        break;
+    }
 
-  g_hash_table_insert (seat->touches, GUINT_TO_POINTER (id), touch);
+  ensure_seat_slot_allocated (seat, seat_slot);
 
-  return touch;
-}
+  touch_state = g_slice_new0 (ClutterTouchState);
+  *touch_state = (ClutterTouchState) {
+    .seat = seat,
+    .seat_slot = seat_slot,
+    .device_slot = device_slot,
+  };
 
-void
-clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat,
-                                 guint32           id)
-{
-  g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id));
+  seat->touch_states[seat_slot] = touch_state;
+
+  return touch_state;
 }
 
-ClutterTouchState *
-clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat,
-                              guint32           id)
+void
+clutter_seat_evdev_release_touch_state (ClutterSeatEvdev  *seat,
+                                        ClutterTouchState *touch_state)
 {
-  return g_hash_table_lookup (seat->touches, GUINT_TO_POINTER (id));
+  g_clear_pointer (&seat->touch_states[touch_state->seat_slot],
+                   (GDestroyNotify) clutter_touch_state_free);
 }
 
 ClutterSeatEvdev *
@@ -154,9 +179,6 @@ clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev)
   _clutter_device_manager_add_device (manager, device);
   seat->core_keyboard = device;
 
-  seat->touches = g_hash_table_new_full (NULL, NULL, NULL,
-                                         (GDestroyNotify) clutter_touch_state_free);
-
   seat->repeat = TRUE;
   seat->repeat_delay = 250;     /* ms */
   seat->repeat_interval = 33;   /* ms */
@@ -824,7 +846,7 @@ clutter_seat_evdev_free (ClutterSeatEvdev *seat)
       g_object_unref (device);
     }
   g_slist_free (seat->devices);
-  g_hash_table_unref (seat->touches);
+  g_free (seat->touch_states);
 
   xkb_state_unref (seat->xkb);
 
diff --git a/clutter/clutter/evdev/clutter-seat-evdev.h b/clutter/clutter/evdev/clutter-seat-evdev.h
index 3bced2da1..0fb89e33e 100644
--- a/clutter/clutter/evdev/clutter-seat-evdev.h
+++ b/clutter/clutter/evdev/clutter-seat-evdev.h
@@ -38,7 +38,10 @@ typedef struct _ClutterTouchState ClutterTouchState;
 
 struct _ClutterTouchState
 {
-  guint32 id;
+  ClutterSeatEvdev *seat;
+
+  int device_slot;
+  int seat_slot;
   ClutterPoint coords;
 };
 
@@ -52,7 +55,8 @@ struct _ClutterSeatEvdev
   ClutterInputDevice *core_pointer;
   ClutterInputDevice *core_keyboard;
 
-  GHashTable *touches;
+  ClutterTouchState **touch_states;
+  int n_alloc_touch_states;
 
   struct xkb_state *xkb;
   xkb_led_index_t caps_lock_led;
@@ -135,11 +139,11 @@ void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev     *seat,
 
 void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
 
-ClutterTouchState * clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat,
-                                                  guint32           id);
+ClutterTouchState * clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat,
+                                                            int               device_slot);
 
-void clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat,
-                                      guint32           id);
+void clutter_seat_evdev_release_touch_state (ClutterSeatEvdev  *seat,
+                                             ClutterTouchState *touch_state);
 
 ClutterTouchState * clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat,
                                                   guint32           id);


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