Commit c55c1d78 authored by Giulio Camuffo's avatar Giulio Camuffo Committed by Pekka Paalanen

Add a resource creation signal

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: default avatarGiulio Camuffo <giulio.camuffo@kdab.com>
Reviewed-by: Jonas Ådahl's avatarJonas Ådahl <jadahl@gmail.com>
[Pekka: added wl_list_remove() in TEST(new_resource).]
Signed-off-by: Pekka Paalanen's avatarPekka Paalanen <pekka.paalanen@collabora.co.uk>
parent 596024f7
......@@ -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
......
......@@ -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
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment