diff --git a/Makefile.am b/Makefile.am index 49e25a66..e684a871 100644 --- a/Makefile.am +++ b/Makefile.am @@ -160,7 +160,8 @@ TESTS = \ signal-test \ resources-test \ message-test \ - headers-test + headers-test \ + compositor-introspection-test if ENABLE_CPP_TEST TESTS += cpp-compile-test @@ -217,6 +218,8 @@ resources_test_SOURCES = tests/resources-test.c resources_test_LDADD = libtest-runner.la message_test_SOURCES = tests/message-test.c message_test_LDADD = libtest-runner.la +compositor_introspection_test_SOURCES = tests/compositor-introspection-test.c +compositor_introspection_test_LDADD = libtest-runner.la headers_test_SOURCES = tests/headers-test.c \ tests/headers-protocol-test.c \ tests/headers-protocol-core-test.c diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h index ad1292f1..43e76fb1 100644 --- a/src/wayland-server-core.h +++ b/src/wayland-server-core.h @@ -151,6 +151,10 @@ void wl_display_add_destroy_listener(struct wl_display *display, struct wl_listener *listener); +void +wl_display_add_client_created_listener(struct wl_display *display, + struct wl_listener *listener); + struct wl_listener * wl_display_get_destroy_listener(struct wl_display *display, wl_notify_func_t notify); diff --git a/src/wayland-server.c b/src/wayland-server.c index 19aa2e8f..b44ec9c1 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -96,6 +96,7 @@ struct wl_display { struct wl_list client_list; struct wl_signal destroy_signal; + struct wl_signal create_client_signal; struct wl_array additional_shm_formats; }; @@ -406,6 +407,9 @@ bind_display(struct wl_client *client, struct wl_display *display); * wl_display_connect_to_fd() on the client side or used with the * WAYLAND_SOCKET environment variable on the client side. * + * Listeners added with wl_display_add_client_created_listener() will + * be notified by this function after the client is fully constructed. + * * On failure this function sets errno accordingly and returns NULL. * * \memberof wl_display @@ -448,6 +452,8 @@ wl_client_create(struct wl_display *display, int fd) wl_list_insert(display->client_list.prev, &client->link); + wl_signal_emit(&display->create_client_signal, client); + return client; err_map: @@ -864,6 +870,7 @@ wl_display_create(void) wl_list_init(&display->registry_resource_list); wl_signal_init(&display->destroy_signal); + wl_signal_init(&display->create_client_signal); display->id = 1; display->serial = 0; @@ -1353,6 +1360,24 @@ wl_display_add_destroy_listener(struct wl_display *display, wl_signal_add(&display->destroy_signal, listener); } +/** Registers a listener for the client connection signal. + * When a new client object is created, \a listener will be notified, carrying + * a pointer to the new wl_client object. + * + * \ref wl_client_create + * \ref wl_display + * \ref wl_listener + * + * \param display The display object + * \param listener Signal handler object + */ +WL_EXPORT void +wl_display_add_client_created_listener(struct wl_display *display, + struct wl_listener *listener) +{ + wl_signal_add(&display->create_client_signal, listener); +} + WL_EXPORT struct wl_listener * wl_display_get_destroy_listener(struct wl_display *display, wl_notify_func_t notify) diff --git a/tests/compositor-introspection-test.c b/tests/compositor-introspection-test.c new file mode 100644 index 00000000..5d2085d4 --- /dev/null +++ b/tests/compositor-introspection-test.c @@ -0,0 +1,87 @@ +/* + * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "wayland-client.h" +#include "wayland-server.h" +#include "test-runner.h" + +/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */ +static const char * +require_xdg_runtime_dir(void) +{ + char *val = getenv("XDG_RUNTIME_DIR"); + assert(val && "set $XDG_RUNTIME_DIR to run this test"); + + return val; +} + +struct compositor { + struct wl_display *display; + struct wl_listener listener; + struct wl_client *client; +}; + +static void +client_created(struct wl_listener *listener, void *data) +{ + struct compositor *c = wl_container_of(listener, c, listener); + c->client = data; +} + +TEST(new_client_connect) +{ + const char *socket; + struct compositor compositor = { 0 }; + struct { + 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); + + client.display = wl_display_connect(socket); + + wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100); + + assert(compositor.client != NULL); + + wl_display_disconnect(client.display); + + wl_client_destroy(compositor.client); + wl_display_destroy(compositor.display); +}