when first being introduced to wayland development, usually from the wayland book, you will notice that there, and in many wayland projects, that the wayland event loop usually consists of the following:
while (wl_display_dispatch(display) != -1) {
/* This space deliberately left blank */
}
which lets libwayland do all of the work of managing and dispatching the wayland queue, but notice that there is a comment right below this snippet:
However, if you have a more sophisticated application, you can build your own event loop in any manner you please, and obtain the Wayland display's file descriptor with wl_display_get_fd. Upon POLLIN events, call wl_display_dispatch to process incoming events. To flush outgoing requests, call wl_display_flush.
for many applications, this might be necessary, such as listening for D-Bus, system signals, stdin, etc; incorporating such an event loop might seem straight forward, but it seems as if most wayland clients do things differently.
reading the wl_display_dispatch
documentation from libwayland, it is
it is mentioned that:
what it essentially means that the helper functions wl_display_prepare_read
and wl_display_dispatch_pending
won't be necessary in a single threaded
application context. however, if multi-threaded, the correct usage, as per
the documentation, would be the following:
while (wl_display_prepare_read_queue(display, queue) != 0)
wl_display_dispatch_queue_pending(display, queue);
wl_display_flush(display);
ret = poll(fds, nfds, -1);
if (has_error(ret))
wl_display_cancel_read(display);
else
wl_display_read_events(display);
keep this in mind as applications later on are looked at.
looking at the source code of wl_display_dispatch
, to it's parent
function after some calls, it looks identical to the multi-threaded
application usage, with the difference of poll being replaced with
wayland's wl_display_poll
.
with this in mind, the following should be the ideal way to do a wayland event loop with a self-managed poll call:
for (;;) {
wl_display_flush(display);
poll(fds, nfds, -1);
/* handle poll error */
if (pfds[WAYLAND_FD].revents & POLLIN)
if (wl_display_dispatch(display) == -1)
/* handle wayland error, usually with breaking */
}
the reason for wl_display_flush
's addition before poll is thanks to it's
documentation mandating so:
Clients should always call this function before blocking on input from the display fd.
usually, flushing of multiple fds is reccomended or required before blocking with poll.
the wl_display_dispatch
might seem out of place in the poll loop, but
since it is not in a loop, it will look identical to a regular poll loop, where
the application reads data from each fd if there is input.
wl_display_dispatch
also handles protocol errors for the user with checking
of EPIPE
too!
let's see how wayland applications do it, starting with mako; it has the ideal event
loop, with the addition of flushing all possible events before blocking,
and flushing on POLLOUT
on the wayland descriptor:
do {
ret = wl_display_dispatch_pending(loop->display);
wl_display_flush(loop->display);
} while (ret > 0);
...
ret = poll(loop->fds, MAKO_EVENT_COUNT, -1);
...
if (loop->fds[MAKO_EVENT_WAYLAND].revents & POLLIN) {
ret = wl_display_dispatch(loop->display);
...
if (loop->fds[MAKO_EVENT_WAYLAND].revents & POLLOUT) {
ret = wl_display_flush(loop->display);
...
mako handles both a wayland and sd_bus queue among others, in which the former can activate the latter, requiring the addition of reading all events before blocking ...just to make sure.
in wlsunset, it handles wayland errors, preparing for reading, cancelling and reading events,
all on its own, rather than simply using wl_display_dispatch
and flushing which is equivalent.
wlsunset is a single-threaded application, which is weird, since it is using multi-threaded
wayland API :p
for fnott, it uses an entire fdm
library for handling many file descriptors, but
for the most part, it only waits till there are events to read in the loop, doesn't
call wl_display_dispatch
, but chooses to do everything manually, which in the
end is actually similar to just doing it with wl_display_dispatch
:pp; however,
the same author wrote wbg, which actually is similar to the ideal event loop :D
do keep in mind that i could be wrong! i'm simply trying my best to read the wayland documentation for the ideal wayland event loops after seeing how different everyone does it, and i think i found my answer as seen above.