aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/wayland-client-core.h7
-rw-r--r--src/wayland-client.c75
-rw-r--r--tests/display-test.c69
3 files changed, 151 insertions, 0 deletions
diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h
index 970e625..e0523e4 100644
--- a/src/wayland-client-core.h
+++ b/src/wayland-client-core.h
@@ -269,9 +269,16 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
struct wl_event_queue *queue);
int
+wl_display_dispatch_queue_pending_single(struct wl_display *display,
+ struct wl_event_queue *queue);
+
+int
wl_display_dispatch_pending(struct wl_display *display);
int
+wl_display_dispatch_pending_single(struct wl_display *display);
+
+int
wl_display_get_error(struct wl_display *display);
uint32_t
diff --git a/src/wayland-client.c b/src/wayland-client.c
index c0b361f..ed686b5 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1882,6 +1882,34 @@ err:
return -1;
}
+
+static int
+dispatch_queue_single(struct wl_display *display, struct wl_event_queue *queue)
+{
+ if (display->last_error)
+ goto err;
+
+ while (!wl_list_empty(&display->display_queue.event_list)) {
+ dispatch_event(display, &display->display_queue);
+ if (display->last_error)
+ goto err;
+ }
+
+ if (!wl_list_empty(&queue->event_list)) {
+ dispatch_event(display, queue);
+ if (display->last_error)
+ goto err;
+ return 1;
+ } else {
+ return 0;
+ }
+
+err:
+ errno = display->last_error;
+
+ return -1;
+}
+
/** Prepare to read events from the display's file descriptor to a queue
*
* \param display The display context object
@@ -2212,6 +2240,34 @@ wl_display_dispatch_queue_pending(struct wl_display *display,
return ret;
}
+/** Dispatch at most one pending event in an event queue
+ *
+ * \param display The display context object
+ * \param queue The event queue to dispatch
+ * \return The number of dispatched events (0 or 1) on success or -1 on failure
+ *
+ * Dispatch at most one pending event for objects assigned to the given
+ * event queue. On failure -1 is returned and errno set appropriately.
+ * If there are no events queued, this function returns immediately.
+ *
+ * \memberof wl_display
+ * \since 1.25.0
+ */
+WL_EXPORT int
+wl_display_dispatch_queue_pending_single(struct wl_display *display,
+ struct wl_event_queue *queue)
+{
+ int ret;
+
+ pthread_mutex_lock(&display->mutex);
+
+ ret = dispatch_queue_single(display, queue);
+
+ pthread_mutex_unlock(&display->mutex);
+
+ return ret;
+}
+
/** Process incoming events
*
* \param display The display context object
@@ -2272,6 +2328,25 @@ wl_display_dispatch_pending(struct wl_display *display)
&display->default_queue);
}
+/** Dispatch at most one pending event in the default event queue.
+ *
+ * \param display The display context object
+ * \return The number of dispatched events (0 or 1) on success or -1 on failure
+ *
+ * Dispatch at most one pending event for objects assigned to the default
+ * event queue. On failure -1 is returned and errno set appropriately.
+ * If there are no events queued, this function returns immediately.
+ *
+ * \memberof wl_display
+ * \since 1.25.0
+ */
+WL_EXPORT int
+wl_display_dispatch_pending_single(struct wl_display *display)
+{
+ return wl_display_dispatch_queue_pending_single(display,
+ &display->default_queue);
+}
+
/** Retrieve the last error that occurred on a display
*
* \param display The display context object
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;