To complement on the new resource created signal, this allows to iterate over the existing resources of a client.
Signed-off-by: Giulio Camuffo <giulio.camu...@kdab.com> Reviewed-by: Jonas Ã…dahl <jad...@gmail.com> --- v3: - add a new wl_iterator_enum to be used instead of the plain int as the return type of the iterator to break the loop src/wayland-private.h | 3 ++- src/wayland-server-core.h | 9 +++++++++ src/wayland-server.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- src/wayland-util.c | 8 ++++++-- src/wayland-util.h | 11 +++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/wayland-private.h b/src/wayland-private.h index adfbe01..ac712d9 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -75,7 +75,8 @@ struct wl_map { uint32_t free_list; }; -typedef void (*wl_iterator_func_t)(void *element, void *data); +typedef enum wl_iterator_result (*wl_iterator_func_t)(void *element, + void *data); void wl_map_init(struct wl_map *map, uint32_t side); diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h index bb0a989..56e8d80 100644 --- a/src/wayland-server-core.h +++ b/src/wayland-server-core.h @@ -216,6 +216,15 @@ void wl_client_add_resource_created_listener(struct wl_client *client, struct wl_listener *listener); +typedef enum wl_iterator_result (*wl_client_for_each_resource_iterator_func_t)( + struct wl_resource *resource, + void *user_data); + +void +wl_client_for_each_resource(struct wl_client *client, + wl_client_for_each_resource_iterator_func_t iterator, + void *user_data); + /** \class wl_listener * * \brief A single listener for Wayland signals diff --git a/src/wayland-server.c b/src/wayland-server.c index 067d8a5..fb44f13 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -565,7 +565,7 @@ wl_resource_post_no_memory(struct wl_resource *resource) WL_DISPLAY_ERROR_NO_MEMORY, "no memory"); } -static void +static enum wl_iterator_result destroy_resource(void *element, void *data) { struct wl_resource *resource = element; @@ -580,6 +580,8 @@ destroy_resource(void *element, void *data) if (!(flags & WL_MAP_ENTRY_LEGACY)) free(resource); + + return WL_ITERATOR_CONTINUE; } WL_EXPORT void @@ -1603,6 +1605,51 @@ wl_client_add_resource_created_listener(struct wl_client *client, wl_signal_add(&client->resource_created_signal, listener); } +struct wl_resource_iterator_context { + void *user_data; + wl_client_for_each_resource_iterator_func_t it; +}; + +static enum wl_iterator_result +resource_iterator_helper(void *res, void *user_data) +{ + struct wl_resource_iterator_context *context = user_data; + struct wl_resource *resource = res; + return context->it(resource, context->user_data); +} + +/** Iterate over all the resources of a client + * + * \param client The client object + * \param iterator The iterator function + * \param user_data The user data pointer + * + * The function pointed by \a iterator will be called for each + * resource owned by the client. The \a user_data will be passed + * as the second argument of the iterator function. + * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration + * will continue, if it returns \a WL_ITERATOR_STOP it will stop. + * + * Creating and destroying resources while iterating is safe, but new + * resources may or may not be picked up by the iterator. + * + * \sa wl_iterator_result + * + * \memberof wl_client + */ +WL_EXPORT void +wl_client_for_each_resource(struct wl_client *client, + wl_client_for_each_resource_iterator_func_t iterator, + void *user_data) +{ + struct wl_resource_iterator_context context = { + .user_data = user_data, + .it = iterator, + }; + + wl_map_for_each(&client->objects, resource_iterator_helper, &context); +} + /** \cond */ /* Deprecated functions below. */ uint32_t diff --git a/src/wayland-util.c b/src/wayland-util.c index 7467366..3c38116 100644 --- a/src/wayland-util.c +++ b/src/wayland-util.c @@ -363,13 +363,17 @@ static void for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data) { union map_entry *start, *end, *p; + enum wl_iterator_result ret; start = entries->data; end = (union map_entry *) ((char *) entries->data + entries->size); for (p = start; p < end; p++) - if (p->data && !map_entry_is_free(*p)) - func(map_entry_get_data(*p), data); + if (p->data && !map_entry_is_free(*p)) { + ret = func(map_entry_get_data(*p), data); + if (ret != WL_ITERATOR_CONTINUE) + break; + } } WL_EXPORT void diff --git a/src/wayland-util.h b/src/wayland-util.h index 8da156c..cacc122 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -311,6 +311,17 @@ typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t, typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0); +/** \enum wl_iterator_result + * + * This enum represents the return value of an iterator function. + */ +enum wl_iterator_result { + /** Stop the iteration */ + WL_ITERATOR_STOP, + /** Continue the iteration */ + WL_ITERATOR_CONTINUE +}; + #ifdef __cplusplus } #endif -- 2.9.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel