Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/ghost/intern/GHOST_SystemWayland.cpp')
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp85
1 files changed, 84 insertions, 1 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 528aa6e1884..7948112c53c 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -69,6 +69,10 @@
#include <cstring>
#include <mutex>
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
+
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
@@ -1456,6 +1460,85 @@ static int memfd_create_sealed(const char *name)
#endif /* !HAVE_MEMFD_CREATE */
}
+enum {
+ GWL_IOR_READ = 1 << 0,
+ GWL_IOR_WRITE = 1 << 1,
+ GWL_IOR_NO_RETRY = 1 << 2,
+};
+
+static int file_descriptor_is_io_ready(int fd, const int flags, const int timeout_ms)
+{
+ int result;
+
+ GHOST_ASSERT(flags & (GWL_IOR_READ | GWL_IOR_WRITE), "X");
+
+ /* Note: We don't bother to account for elapsed time if we get EINTR */
+ do {
+#ifdef HAVE_POLL
+ struct pollfd info;
+
+ info.fd = fd;
+ info.events = 0;
+ if (flags & GWL_IOR_READ) {
+ info.events |= POLLIN | POLLPRI;
+ }
+ if (flags & GWL_IOR_WRITE) {
+ info.events |= POLLOUT;
+ }
+ result = poll(&info, 1, timeout_ms);
+#else
+ fd_set rfdset, *rfdp = nullptr;
+ fd_set wfdset, *wfdp = nullptr;
+ struct timeval tv, *tvp = nullptr;
+
+ /* If this assert triggers we'll corrupt memory here */
+ GHOST_ASSERT(fd >= 0 && fd < FD_SETSIZE, "X");
+
+ if (flags & GWL_IOR_READ) {
+ FD_ZERO(&rfdset);
+ FD_SET(fd, &rfdset);
+ rfdp = &rfdset;
+ }
+ if (flags & GWL_IOR_WRITE) {
+ FD_ZERO(&wfdset);
+ FD_SET(fd, &wfdset);
+ wfdp = &wfdset;
+ }
+
+ if (timeout_ms >= 0) {
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+ tvp = &tv;
+ }
+
+ result = select(fd + 1, rfdp, wfdp, nullptr, tvp);
+#endif /* !HAVE_POLL */
+ } while (result < 0 && errno == EINTR && !(flags & GWL_IOR_NO_RETRY));
+
+ return result;
+}
+
+static int ghost_wl_display_event_pump(struct wl_display *wl_display)
+{
+ /* Based on SDL's `Wayland_PumpEvents`. */
+ int err;
+ if (wl_display_prepare_read(wl_display) == 0) {
+ /* Use #GWL_IOR_NO_RETRY to ensure #SIGINT will break us out of our wait. */
+ if (file_descriptor_is_io_ready(
+ wl_display_get_fd(wl_display), GWL_IOR_READ | GWL_IOR_NO_RETRY, 0) > 0) {
+ err = wl_display_read_events(wl_display);
+ }
+ else {
+ wl_display_cancel_read(wl_display);
+ err = 0;
+ }
+ }
+ else {
+ err = wl_display_dispatch_pending(wl_display);
+ }
+ return err;
+}
+
static size_t ghost_wl_shm_format_as_size(enum wl_shm_format format)
{
switch (format) {
@@ -5169,7 +5252,7 @@ bool GHOST_SystemWayland::processEvents(bool waitForEvent)
}
}
else {
- if (wl_display_roundtrip(display_->wl_display) == -1) {
+ if (ghost_wl_display_event_pump(display_->wl_display) == -1) {
ghost_wl_display_report_error(display_->wl_display);
}
}