diff options
| author | Isaac Freund <mail@isaacfreund.com> | 2025-07-02 12:15:33 +0200 |
|---|---|---|
| committer | Pekka Paalanen <pq@iki.fi> | 2025-09-16 11:48:33 +0300 |
| commit | d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c (patch) | |
| tree | 13a938fa46e67c22a290c52b54188db492262f62 /tests | |
| parent | connection: Add a thread ID to WAYLAND_DEBUG output. (diff) | |
| download | wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar.gz wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar.bz2 wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar.lz wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar.xz wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.tar.zst wayland-d81525a235e48cc5de3e4005a16ddb1fbdfd9d7c.zip | |
client: add wl_display_dispatch_pending_single
As well as wl_display_dispatch_queue_pending_single.
The motivation is writing libwayland bindings for a dynamic language
with exceptions/non-local returns. Since it is invalid for a
wl_dispatcher_func_t callback provided to libwayland to not return,
there is no way to prevent dispatching of further events in the case of
an exception in the dynamic language event handler.
Furthermore, since creating/destroying Wayland objects in an event
handler affects the dispatching of subsequent events by libwayland,
it is not possible to collect Wayland events in a queue outside
libwayland and dispatch them one-by-one after
wl_display_dispatch_pending() returns.
Adding libwayland API to dispatch at most one pending event solves this
problem cleanly. The bindings can have libwayland dispatch a single
event, wait for wl_display_dispatch_pending_single() to return, run the
dynamic language event handler (which may longjmp away), and continue
the loop for as long as there are more events to dispatch.
References: https://codeberg.org/ifreund/janet-wayland
Signed-off-by: Isaac Freund <mail@isaacfreund.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/display-test.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/tests/display-test.c b/tests/display-test.c index 89606c7..fe78b52 100644 --- a/tests/display-test.c +++ b/tests/display-test.c @@ -1696,6 +1696,75 @@ TEST(global_remove) } static void +dispatch_single_read_events(struct wl_display *d) +{ + if (wl_display_prepare_read(d) < 0) { + return; + } + + int ret = 0; + do { + ret = wl_display_flush(d); + } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); + assert(ret >= 0); + + struct pollfd pfd[1]; + pfd[0].fd = wl_display_get_fd(d); + pfd[0].events = POLLIN; + + do { + ret = poll(pfd, 1, -1); + } while (ret < 0 && errno == EINTR); + assert(ret > 0); + + wl_display_read_events(d); +} + +static void +dispatch_single_client(void) +{ + struct client *c = client_connect(); + + assert(wl_display_dispatch_pending_single(c->wl_display) == 0); + + struct wl_registry *registry = wl_display_get_registry(c->wl_display); + + dispatch_single_read_events(c->wl_display); + + // [1815110.061] {Default Queue} wl_registry#3.global(1, "test", 1) + assert(wl_display_dispatch_pending_single(c->wl_display) == 1); + + dispatch_single_read_events(c->wl_display); + + // [1815110.067] {Default Queue} wl_registry#3.global(2, "wl_seat", 1) + assert(wl_display_dispatch_pending_single(c->wl_display) == 1); + + // No more events + assert(wl_display_dispatch_pending_single(c->wl_display) == 0); + + wl_registry_destroy(registry); + + client_disconnect(c); +} + +TEST(dispatch_single) +{ + struct display *d = display_create(); + + struct wl_global *global = wl_global_create(d->wl_display, + &wl_seat_interface, + 1, d, bind_seat); + + client_create_noarg(d, dispatch_single_client); + + display_run(d); + + wl_global_destroy(global); + + display_destroy(d); +} + +static void terminate_display(void *arg) { struct wl_display *wl_display = arg; |
