From b6477a826d37cebc96ae41e86a555212ca4411ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sat, 27 Jan 2018 00:25:56 +0800 Subject: [PATCH] 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. --- .../evdev/clutter-device-manager-evdev.c | 48 +++++++------- .../evdev/clutter-input-device-evdev.c | 65 ++++++++++++++++++ .../evdev/clutter-input-device-evdev.h | 15 +++++ clutter/clutter/evdev/clutter-seat-evdev.c | 66 ++++++++++++------- clutter/clutter/evdev/clutter-seat-evdev.h | 16 +++-- 5 files changed, 156 insertions(+), 54 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); } -ClutterTouchState * -clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat, - guint32 id) +static void +ensure_seat_slot_allocated (ClutterSeatEvdev *seat, + int seat_slot) { - ClutterTouchState *touch; + if (seat_slot >= seat->n_alloc_touch_states) + { + const int size_increase = 5; + int i; - touch = g_slice_new0 (ClutterTouchState); - touch->id = id; + 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; + } +} - g_hash_table_insert (seat->touches, GUINT_TO_POINTER (id), touch); +ClutterTouchState * +clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat, + int device_slot) +{ + ClutterTouchState *touch_state; + int seat_slot; - return touch; + for (seat_slot = 0; seat_slot < seat->n_alloc_touch_states; seat_slot++) + { + if (!seat->touch_states[seat_slot]) + break; + } + + ensure_seat_slot_allocated (seat, seat_slot); + + touch_state = g_slice_new0 (ClutterTouchState); + *touch_state = (ClutterTouchState) { + .seat = seat, + .seat_slot = seat_slot, + .device_slot = device_slot, + }; + + seat->touch_states[seat_slot] = touch_state; + + return touch_state; } void -clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat, - guint32 id) +clutter_seat_evdev_release_touch_state (ClutterSeatEvdev *seat, + ClutterTouchState *touch_state) { - g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id)); -} - -ClutterTouchState * -clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat, - guint32 id) -{ - 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);