---
If a surface is not visible because the output is powered off or a
screen locker is already running, frame_callback_handle_done() won't be
called. If the output was turned off manually, chayang starts to run at
some point and the output is turned on again by moving the cursor (or
something similar), chayang would exit with an exit code != 0 and the
screen locker isn't active (although it should be).
This patch should fix this issue by timing out while reading from the
display file descriptor and checking if the specified delay is over.
main.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/main.c b/main.c
index 4180f69..b30dbb1 100644
--- a/main.c+++ b/main.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <errno.h>
+#include <poll.h>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,9 +46,8 @@ static const struct wl_callback_listener frame_callback_listener = {
static void repaint_output(struct chayang_output *output) {
int64_t delta = now_ms() - output->chayang->start_time_ms;
double progress = (double)delta / output->chayang->delay_ms;
- if (progress >= 1) {- output->chayang->running = false;- return;+ if (progress > 1) {+ progress = 1; }
uint32_t alpha = progress * UINT32_MAX;
@@ -342,8 +342,48 @@ int main(int argc, char *argv[]) {
state.running = true;
state.start_time_ms = now_ms();
while (state.running) {
- if (wl_display_dispatch(display) < 0) {- fprintf(stderr, "wl_display_dispatch() failed\n");+ int flush_res;+ while ((flush_res = wl_display_flush(display)) == -1 && errno == EAGAIN);+ if (flush_res == -1) {+ wl_display_cancel_read(display);+ fprintf(stderr, "wl_display_flush() failed\n");+ ret = 1;+ break;+ }+ while (wl_display_prepare_read(display) != 0) {+ if (wl_display_dispatch_pending(display) == -1) {+ fprintf(stderr, "wl_display_dispatch_pending() failed\n");+ ret = 1;+ break;+ }+ }+ struct pollfd fds = {+ .fd = wl_display_get_fd(display),+ .events = POLLIN+ };+ int64_t delta = now_ms() - state.start_time_ms;+ if (delta >= state.delay_ms) {+ wl_display_cancel_read(display);+ state.running = false;+ break;+ }+ int poll_res = poll(&fds, 1, state.delay_ms - delta);+ if (poll_res <= 0) {+ wl_display_cancel_read(display);+ if (poll_res < 0) {+ fprintf(stderr, "polling the display file descriptor failed\n");+ ret = 1;+ break;+ }+ } else if (poll_res > 0) {+ if (wl_display_read_events(display)) {+ fprintf(stderr, "wl_display_read_events() failed\n");+ ret = 1;+ break;+ }+ }+ if (wl_display_dispatch_pending(display) == -1) {+ fprintf(stderr, "wl_display_dispatch_pending() failed\n"); ret = 1;
break;
}
--
2.46.1