Remix.run Logo
mizmar 14 hours ago

>and I still don't know what's the difference between them (wl_display_roundtrip() & wl_display_dispatch()) and in what order to call them on

I've been struggling with this initially as well, it's pretty poorly explained in docs. Short explanation:

Wayland-client library implements a queues over the socket. So to get it, you have to think about when is the socket read from and written to, and when are the queues pulled from or pushed to. There is always a default queue, but for example EGL+OpenGL creates it's own queue, which further makes it more confusing.

- `wl_display_dispatch_pending()` only pulls messages from default queue to callbacks

- `wl_display_dispatch()` also tries to do blocking read on the socket if no messages are in queue

- quite recently `wl_display_dispatch_queue_timeout()` was finally added, so you can do non-blocking read from the socket. earlier you had to hack the function yourself

- `wl_display_flush()` writes enqueued messages in queue to socket

- `wl_display_roundtrip()` sends a ping message and does blocking wait for response. the purpose is that you also send all enqueued requests and receive and process all responses. for example during init you call it to create registry and enumerate the objects, and you call it for second time to enumerate further protocol objects that got registered in registry callback, such as seat

- `eglSwapBuffers()` operates on its own queue, but reading from socket also enqueues to default queue, so you should always call `wl_display_dispatch_pending()` (on default queue) afterwards

There is also a way to get around being stuck in `eglSwapBuffers()` during window inhibition: disable the blocking with `eglSwapInterval(0)` and use `wl_surface_frame()` callback, and you get notified in callback when you can redraw and swap again. But you can't do blocking reads with `wl_display_dispatch()` anymore, have to use the timeout variant. After using it this way, you can also easily manage multiple vsynced windows independently on the same thread, and even use wayland socket in epoll event loop. None of this is documented of course.

The clipboard interface is definitely compromised a bit by being shared with drag-and-drop events, but it's not that complicated. Also there is a pitfall when you copy-paste to your own application and don't use any async event loop, you can get deadlocked by being expected to write and read on the same file descriptor at the same time.