From c55c1d787cb542de5ffee702c7ca9bcd27b56bef Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Thu, 11 Aug 2016 17:23:09 +0200 Subject: [PATCH] Add a resource creation signal MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Jonas Ådahl [Pekka: added wl_list_remove() in TEST(new_resource).] Signed-off-by: Pekka Paalanen --- src/wayland-server-core.h | 4 ++ src/wayland-server.c | 33 ++++++++++++++ tests/compositor-introspection-test.c | 81 +++++++++++++++++++++++++++++++---- 3 files changed, 109 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..83194ce 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,54 @@ 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++; +} + +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); - wl_client_destroy(compositor.client); - wl_display_destroy(compositor.display); + /* This is defined to be safe also after client destruction */ + wl_list_remove(&resource_listener.listener.link); } -- 2.7.4