mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	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: Giulio Camuffo <giulio.camuffo@kdab.com> Reviewed-by: Jonas Ådahl <jadahl@gmail.com> [Pekka: added wl_list_remove() in TEST(new_resource).] Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
		
							parent
							
								
									596024f728
								
							
						
					
					
						commit
						c55c1d787c
					
				
					 3 changed files with 110 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
	wl_client_destroy(compositor.client);
 | 
			
		||||
	wl_display_destroy(compositor.display);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	/* This is defined to be safe also after client destruction */
 | 
			
		||||
	wl_list_remove(&resource_listener.listener.link);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue