wayland: Only send full sequences of touch events to clients

If input happens to be grabbed somewhere along the shell, and ungrabbed
while a touch operation is ongoing, the wayland bits will happily start
sending wl_touch.update events from an undeterminate point, without
clients having ever received wl_touch.down for that id.

Consider those touches grabbed for the entirety of their lifetime, if
wl_touch.down wasn't received by the client, no other events will.

https://bugzilla.gnome.org/show_bug.cgi?id=776220
This commit is contained in:
Carlos Garnacho 2017-12-21 11:30:16 +01:00
parent 49f029571c
commit 798026498d

View File

@ -56,6 +56,7 @@ struct _MetaWaylandTouchInfo
gfloat x; gfloat x;
gfloat y; gfloat y;
guint updated : 1; guint updated : 1;
guint begin_delivered : 1;
}; };
static void static void
@ -278,6 +279,8 @@ handle_touch_begin (MetaWaylandTouch *touch,
wl_fixed_from_double (touch_info->x), wl_fixed_from_double (touch_info->x),
wl_fixed_from_double (touch_info->y)); wl_fixed_from_double (touch_info->y));
} }
touch_info->begin_delivered = TRUE;
} }
static void static void
@ -292,7 +295,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) if (!touch_info || !touch_info->begin_delivered)
return; return;
l = &touch_info->touch_surface->resource_list; l = &touch_info->touch_surface->resource_list;
@ -321,12 +324,15 @@ handle_touch_end (MetaWaylandTouch *touch,
if (!touch_info) if (!touch_info)
return; return;
l = &touch_info->touch_surface->resource_list; if (touch_info->begin_delivered)
wl_resource_for_each(resource, l)
{ {
wl_touch_send_up (resource, touch_info->slot_serial, l = &touch_info->touch_surface->resource_list;
clutter_event_get_time (event), wl_resource_for_each(resource, l)
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);