[PATCH wayland v4 1/3] Add a resource creation signal

Giulio Camuffo giuliocamuffo at gmail.com
Thu Aug 11 15:23:09 UTC 2016


This change allows to add a resource creation listener to a wl_client,
which will be notified when a new resource is created for that client.
The alternative would be to have a per wl_display listener, but i think
that resources are really client specific objects, so it makes sense
to use the wl_client as the context.

Signed-off-by: Giulio Camuffo <giulio.camuffo at kdab.com>
Reviewed-by: Jonas Ã…dahl <jadahl at gmail.com>
---

v4: - added a test
    - allow removing the listeners after the client was destroyed

 src/wayland-server-core.h             |  4 ++
 src/wayland-server.c                  | 33 +++++++++++++++
 tests/compositor-introspection-test.c | 78 +++++++++++++++++++++++++++++++----
 3 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
index 69c09dc..bb0a989 100644
--- a/src/wayland-server-core.h
+++ b/src/wayland-server-core.h
@@ -212,6 +212,10 @@ wl_client_get_object(struct wl_client *client, uint32_t id);
 void
 wl_client_post_no_memory(struct wl_client *client);
 
+void
+wl_client_add_resource_created_listener(struct wl_client *client,
+                                        struct wl_listener *listener);
+
 /** \class wl_listener
  *
  * \brief A single listener for Wayland signals
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 2dd9a4a..a396410 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -81,6 +81,7 @@ struct wl_client {
 	struct wl_signal destroy_signal;
 	struct ucred ucred;
 	int error;
+	struct wl_signal resource_created_signal;
 };
 
 struct wl_display {
@@ -424,6 +425,7 @@ wl_client_create(struct wl_display *display, int fd)
 	if (client == NULL)
 		return NULL;
 
+	wl_signal_init(&client->resource_created_signal);
 	client->display = display;
 	client->source = wl_event_loop_add_fd(display->loop, fd,
 					      WL_EVENT_READABLE,
@@ -729,6 +731,7 @@ wl_client_destroy(struct wl_client *client)
 	wl_event_source_remove(client->source);
 	close(wl_connection_destroy(client->connection));
 	wl_list_remove(&client->link);
+	wl_list_remove(&client->resource_created_signal.listener_list);
 	free(client);
 }
 
@@ -1420,6 +1423,18 @@ wl_resource_set_dispatcher(struct wl_resource *resource,
 	resource->destroy = destroy;
 }
 
+/** Create a new resource object
+ *
+ * \param client The client owner of the new resource.
+ * \param interface The interface of the new resource.
+ * \param version The version of the new resource.
+ * \param id The id of the new resource. If 0, an available id will be used.
+ *
+ * Listeners added with \a wl_client_add_resource_created_listener will be
+ * notified at the end of this function.
+ *
+ * \memberof wl_resource
+ */
 WL_EXPORT struct wl_resource *
 wl_resource_create(struct wl_client *client,
 		   const struct wl_interface *interface,
@@ -1454,6 +1469,7 @@ wl_resource_create(struct wl_client *client,
 		return NULL;
 	}
 
+	wl_signal_emit(&client->resource_created_signal, resource);
 	return resource;
 }
 
@@ -1571,6 +1587,23 @@ wl_client_from_link(struct wl_list *link)
 	return container_of(link, struct wl_client, link);
 }
 
+/** Add a listener for the client's resource creation signal
+ *
+ * \param client The client object
+ * \param listener The listener to be added
+ *
+ * When a new resource is created for this client the listener
+ * will be notified, carrying the new resource as the data argument.
+ *
+ * \memberof wl_client
+ */
+WL_EXPORT void
+wl_client_add_resource_created_listener(struct wl_client *client,
+					struct wl_listener *listener)
+{
+	wl_signal_add(&client->resource_created_signal, listener);
+}
+
 /** \cond */ /* Deprecated functions below. */
 
 uint32_t
diff --git a/tests/compositor-introspection-test.c b/tests/compositor-introspection-test.c
index 50ff1dd..70d5f30 100644
--- a/tests/compositor-introspection-test.c
+++ b/tests/compositor-introspection-test.c
@@ -78,6 +78,29 @@ check_client_list(struct compositor *compositor)
 	assert(compositor->client == client);
 }
 
+static const char *
+setup_compositor(struct compositor *compositor)
+{
+	const char *socket;
+
+	require_xdg_runtime_dir();
+
+	compositor->display = wl_display_create();
+	socket = wl_display_add_socket_auto(compositor->display);
+
+	compositor->listener.notify = client_created;
+	wl_display_add_client_created_listener(compositor->display, &compositor->listener);
+
+	return socket;
+}
+
+static void
+cleanup_compositor(struct compositor *compositor)
+{
+	wl_client_destroy(compositor->client);
+	wl_display_destroy(compositor->display);
+}
+
 TEST(new_client_connect)
 {
 	const char *socket;
@@ -86,13 +109,7 @@ TEST(new_client_connect)
 		struct wl_display *display;
 	} client;
 
-	require_xdg_runtime_dir();
-
-	compositor.display = wl_display_create();
-	socket = wl_display_add_socket_auto(compositor.display);
-
-	compositor.listener.notify = client_created;
-	wl_display_add_client_created_listener(compositor.display, &compositor.listener);
+	socket = setup_compositor(&compositor);
 
 	client.display = wl_display_connect(socket);
 
@@ -102,8 +119,51 @@ TEST(new_client_connect)
 
 	check_client_list(&compositor);
 
+
+
 	wl_display_disconnect(client.display);
+	cleanup_compositor(&compositor);
+}
+
+struct resource_listener {
+	struct wl_listener listener;
+	int count;
+};
+
+static void
+resource_created(struct wl_listener *listener, void *data)
+{
+	struct resource_listener *l;
+	l = wl_container_of(listener, l, listener);
+	l->count++;
+}
 
-	wl_client_destroy(compositor.client);
-	wl_display_destroy(compositor.display);
+TEST(new_resource)
+{
+	const char *socket;
+	struct compositor compositor = { 0 };
+	struct {
+		struct wl_display *display;
+		struct wl_callback *cb;
+	} client;
+	struct resource_listener resource_listener;
+
+	socket = setup_compositor(&compositor);
+	client.display = wl_display_connect(socket);
+	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
+
+	resource_listener.count = 0;
+	resource_listener.listener.notify = resource_created;
+	wl_client_add_resource_created_listener(compositor.client,
+						&resource_listener.listener);
+
+	client.cb = wl_display_sync(client.display);
+	wl_display_flush(client.display);
+	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
+
+	assert(resource_listener.count == 1);
+
+	wl_callback_destroy(client.cb);
+	wl_display_disconnect(client.display);
+	cleanup_compositor(&compositor);
 }
-- 
2.9.2



More information about the wayland-devel mailing list