diff --git a/render.c b/render.c index 4b012a90..25432110 100644 --- a/render.c +++ b/render.c @@ -867,7 +867,7 @@ grid_render(struct terminal *term) } wl_surface_commit(term->window->surface); - wl_display_flush(term->wl->display); + wayl_flush(term->wl); #if TIME_FRAME_RENDERING struct timeval end_time; diff --git a/wayland.c b/wayland.c index c0b305ca..6e4bb638 100644 --- a/wayland.c +++ b/wayland.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -573,7 +574,7 @@ fdm_wayl(struct fdm *fdm, int fd, int events, void *data) return false; } - wl_display_flush(wayl->display); + wayl_flush(wayl); return event_count != -1; } @@ -983,7 +984,7 @@ wayl_cursor_set(struct wayland *wayl, const struct terminal *term) wl_surface_set_buffer_scale(wayl->pointer.surface, scale); wl_surface_commit(wayl->pointer.surface); - wl_display_flush(wayl->display); + wayl_flush(wayl); return true; } @@ -1029,6 +1030,46 @@ wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface) return NULL; } +void +wayl_flush(struct wayland *wayl) +{ + while (true) { + int r = wl_display_flush(wayl->display); + if (r >= 0) + return; + + if (errno == EINTR) + continue; + + if (errno != EAGAIN) { + LOG_ERRNO("failed to flush wayland socket"); + return; + } + + struct pollfd fds[] = { + {.fd = wl_display_get_fd(wayl->display), .events = POLLOUT} + }; + + while (true) { + r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1); + + if (r < 0) { + if (errno == EINTR) + continue; + + LOG_ERRNO("failed to poll"); + return; + } + + if (fds[0].revents & POLLHUP) + return; + + assert(fds[0].revents & POLLOUT); + break; + } + } +} + void wayl_roundtrip(struct wayland *wayl) { @@ -1037,5 +1078,5 @@ wayl_roundtrip(struct wayland *wayl) while (wl_display_prepare_read(wayl->display) != 0) wl_display_dispatch_pending(wayl->display); - wl_display_flush(wayl->display); + wayl_flush(wayl); } diff --git a/wayland.h b/wayland.h index eda9e009..ad352797 100644 --- a/wayland.h +++ b/wayland.h @@ -178,6 +178,7 @@ struct wayland { struct wayland *wayl_init(const struct config *conf, struct fdm *fdm); void wayl_destroy(struct wayland *wayl); +void wayl_flush(struct wayland *wayl); void wayl_roundtrip(struct wayland *wayl); struct terminal *wayl_terminal_from_surface(