From f87d4f856a277553be35fbee8c3abe2765d978dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 3 Jul 2019 15:16:38 +0200 Subject: [PATCH] main: mitigate screen flashes on slow client If a client writes to the PTY "too slow", we often end up flashing the screen. This could for example be caused by a client first erasing a line, then we render that frame, followed by the client updating the just-erased line. When we render _that_ frame, it will be perceived as a flash. Mitigate this by trying to read client data again, after finishing processing one batch, but before rendering. To avoid hanging on client output (and never rendering anything), limit this to at most 3 iterations. This may have to be tweaked. --- main.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/main.c b/main.c index a29f5d8c..133880ee 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include //#include @@ -987,6 +988,20 @@ main(int argc, char *const *argv) break; } + /* Read logic requires non-blocking mode */ + { + int fd_flags = fcntl(c.term.ptmx, F_GETFL); + if (fd_flags == -1) { + LOG_ERRNO("failed to set non blocking mode on PTY master"); + goto out; + } + + if (fcntl(c.term.ptmx, F_SETFL, fd_flags | O_NONBLOCK) == -1) { + LOG_ERRNO("failed to set non blocking mode on PTY master"); + goto out; + } + } + while (true) { struct pollfd fds[] = { {.fd = wl_display_get_fd(c.wl.display), .events = POLLIN}, @@ -1011,16 +1026,18 @@ main(int argc, char *const *argv) } if (fds[1].revents & POLLIN) { - uint8_t data[8192]; - ssize_t count = read(c.term.ptmx, data, sizeof(data)); - if (count < 0) { - LOG_ERRNO("failed to read from pseudo terminal"); - break; + for (size_t i = 0; i < 3; i++) { + uint8_t data[8192]; + ssize_t count = read(c.term.ptmx, data, sizeof(data)); + if (count < 0) { + if (errno != EAGAIN) + LOG_ERRNO("failed to read from pseudo terminal"); + break; + } + + vt_from_slave(&c.term, data, count); } - //LOG_DBG("%.*s", (int)count, data); - - vt_from_slave(&c.term, data, count); if (!c.frame_is_scheduled) grid_render(&c); }