wayland/touch: Remove undelivered touches earlier

When the touch_down event was not delivered to Wayland clients, there's
no point in keeping the touchpoint in our list, so remove it early
inside update() instead of removing it after the touch ended.

This fixes a crash inside touch_handle_surface_destroy() where the
assertion to make sure the surface is removed fails because the
touch_count of the surface never reached 0. This in turn happened
because a new sequence was added, while a (already ended one) wasn't
removed from the touch->touches list before. This caused the touch
counter to get incremented by 1 while no new sequence was added to the
list (because Clutter reuses sequence IDs, the old sequence is equal to
the new one, i.e. the new sequence already is present in the list).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/200

https://gitlab.gnome.org/GNOME/mutter/merge_requests/426
This commit is contained in:
Jonas Dreßler 2019-02-19 12:16:29 +01:00 committed by Jonas Ådahl
parent 1c6ea5d1db
commit 8d9a5e3c7e

View File

@ -243,6 +243,13 @@ meta_wayland_touch_update (MetaWaylandTouch *touch,
if (!touch_info) if (!touch_info)
return; return;
if (event->type != CLUTTER_TOUCH_BEGIN &&
!touch_info->begin_delivered)
{
g_hash_table_remove (touch->touches, sequence);
return;
}
if (event->type == CLUTTER_TOUCH_BEGIN || if (event->type == CLUTTER_TOUCH_BEGIN ||
event->type == CLUTTER_TOUCH_END) event->type == CLUTTER_TOUCH_END)
{ {
@ -302,7 +309,7 @@ handle_touch_update (MetaWaylandTouch *touch,
sequence = clutter_event_get_event_sequence (event); sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE); touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info || !touch_info->begin_delivered) if (!touch_info)
return; return;
l = &touch_info->touch_surface->resource_list; l = &touch_info->touch_surface->resource_list;
@ -333,15 +340,12 @@ handle_touch_end (MetaWaylandTouch *touch,
if (!touch_info) if (!touch_info)
return; return;
if (touch_info->begin_delivered) l = &touch_info->touch_surface->resource_list;
wl_resource_for_each (resource, l)
{ {
l = &touch_info->touch_surface->resource_list; wl_touch_send_up (resource, touch_info->slot_serial,
wl_resource_for_each(resource, l) clutter_event_get_time (event),
{ touch_info->slot);
wl_touch_send_up (resource, touch_info->slot_serial,
clutter_event_get_time (event),
touch_info->slot);
}
} }
g_hash_table_remove (touch->touches, sequence); g_hash_table_remove (touch->touches, sequence);