From c3f03f557b49f701c13557f266a57e0aa0ecf310 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Wed, 7 May 2014 11:57:27 +0300 Subject: [PATCH] simple-touch: Handle multiple seats properly If simple-touch ran on a compositor with multiple seats, and the first one happened to have the touch capability while the second one didn't, the handler for seat capabilities would destroy the wl_touch device it created on the first call for the first seat when it was called a again for the second seat that has not touch capabilities. Fix this problem by creating a separate struct for each seat. https://bugs.freedesktop.org/show_bug.cgi?id=78365 --- clients/simple-touch.c | 48 +++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/clients/simple-touch.c b/clients/simple-touch.c index b5a84d78..d8439aca 100644 --- a/clients/simple-touch.c +++ b/clients/simple-touch.c @@ -36,14 +36,18 @@ #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +struct seat { + struct touch *touch; + struct wl_seat *seat; + struct wl_touch *wl_touch; +}; + struct touch { struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_shell *shell; struct wl_shm *shm; - struct wl_seat *seat; - struct wl_touch *wl_touch; struct wl_pointer *pointer; struct wl_keyboard *keyboard; struct wl_surface *surface; @@ -199,18 +203,19 @@ static const struct wl_touch_listener touch_listener = { }; static void -seat_handle_capabilities(void *data, struct wl_seat *seat, +seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { - struct touch *touch = data; - - if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !touch->wl_touch) { - touch->wl_touch = wl_seat_get_touch(seat); - wl_touch_set_user_data(touch->wl_touch, touch); - wl_touch_add_listener(touch->wl_touch, &touch_listener, touch); - } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && touch->wl_touch) { - wl_touch_destroy(touch->wl_touch); - touch->wl_touch = NULL; + struct seat *seat = data; + struct touch *touch = seat->touch; + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !seat->wl_touch) { + seat->wl_touch = wl_seat_get_touch(wl_seat); + wl_touch_set_user_data(seat->wl_touch, touch); + wl_touch_add_listener(seat->wl_touch, &touch_listener, touch); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) { + wl_touch_destroy(seat->wl_touch); + seat->wl_touch = NULL; } } @@ -218,6 +223,21 @@ static const struct wl_seat_listener seat_listener = { seat_handle_capabilities, }; +static void +add_seat(struct touch *touch, uint32_t name, uint32_t version) +{ + struct seat *seat; + + seat = malloc(sizeof *seat); + assert(seat); + + seat->touch = touch; + seat->wl_touch = NULL; + seat->seat = wl_registry_bind(touch->registry, name, + &wl_seat_interface, 1); + wl_seat_add_listener(seat->seat, &seat_listener, seat); +} + static void handle_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) @@ -261,9 +281,7 @@ handle_global(void *data, struct wl_registry *registry, &wl_shm_interface, 1); wl_shm_add_listener(touch->shm, &shm_listener, touch); } else if (strcmp(interface, "wl_seat") == 0) { - touch->seat = wl_registry_bind(registry, name, - &wl_seat_interface, 1); - wl_seat_add_listener(touch->seat, &seat_listener, touch); + add_seat(touch, name, version); } }