Previously simple-touch would only handle one seat. If there were multiple seats it would lose track of whether there is a touch device available depending on what order the capability events arrive in. This makes it keep a linked list of seats and to track a separate touch device for each seat so that it doesn't matter what order they arrive in.
https://bugs.freedesktop.org/show_bug.cgi?id=78365 --- clients/simple-touch.c | 77 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/clients/simple-touch.c b/clients/simple-touch.c index b5a84d7..a45de46 100644 --- a/clients/simple-touch.c +++ b/clients/simple-touch.c @@ -42,18 +42,25 @@ struct touch { 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; struct wl_shell_surface *shell_surface; struct wl_buffer *buffer; + struct wl_list seats; int has_argb; int width, height; void *data; }; +struct touch_seat { + struct touch *touch; + struct wl_touch *wl_touch; + struct wl_seat *wl_seat; + struct wl_list link; + uint32_t name; +}; + static void create_shm_buffer(struct touch *touch) { @@ -156,7 +163,8 @@ touch_handle_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) { - struct touch *touch = data; + struct touch_seat *seat = data; + struct touch *touch = seat->touch; float x = wl_fixed_to_double(x_w); float y = wl_fixed_to_double(y_w); @@ -173,7 +181,8 @@ static void touch_handle_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) { - struct touch *touch = data; + struct touch_seat *seat = data; + struct touch *touch = seat->touch; float x = wl_fixed_to_double(x_w); float y = wl_fixed_to_double(y_w); @@ -199,18 +208,18 @@ 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 touch_seat *seat = data; + + 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, seat); + wl_touch_add_listener(seat->wl_touch, &touch_listener, seat); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && seat->wl_touch) { + wl_touch_destroy(seat->wl_touch); + seat->wl_touch = NULL; } } @@ -243,6 +252,31 @@ static const struct wl_shell_surface_listener shell_surface_listener = { }; static void +add_seat(struct touch *touch, uint32_t name) +{ + struct touch_seat *seat; + + seat = malloc(sizeof *seat); + seat->touch = touch; + seat->wl_seat = wl_registry_bind(touch->registry, name, + &wl_seat_interface, 1); + seat->name = name; + seat->wl_touch = NULL; + wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + wl_list_insert(&touch->seats, &seat->link); +} + +static void +remove_seat(struct touch_seat *seat) +{ + if (seat->wl_touch) + wl_touch_destroy(seat->wl_touch); + wl_seat_destroy(seat->wl_seat); + wl_list_remove(&seat->link); + free(seat); +} + +static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { @@ -261,15 +295,22 @@ 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); } } static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { + struct touch *touch = data; + struct touch_seat *seat; + + wl_list_for_each(seat, &touch->seats, link) { + if (seat->name == name) { + remove_seat(seat); + break; + } + } } static const struct wl_registry_listener registry_listener = { @@ -290,6 +331,8 @@ touch_create(int width, int height) touch->display = wl_display_connect(NULL); assert(touch->display); + wl_list_init(&touch->seats); + touch->has_argb = 0; touch->registry = wl_display_get_registry(touch->display); wl_registry_add_listener(touch->registry, ®istry_listener, touch); -- 1.9.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel