[PATCH weston] simple-touch: Handle multiple seats

Neil Roberts neil at linux.intel.com
Wed May 7 07:00:37 PDT 2014


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, &registry_listener, touch);
-- 
1.9.0



More information about the wayland-devel mailing list