From 311623d4c14c59db1ebdf87c372baf601226398e Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Fri, 12 Jul 2019 23:32:44 +0100 Subject: Modernise event loop --- src/imv.c | 10 ++++------ src/window.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/imv.c b/src/imv.c index 299dddb..6518f75 100644 --- a/src/imv.c +++ b/src/imv.c @@ -1017,10 +1017,10 @@ int imv_run(struct imv *imv) double dt = current_time - last_time; imv->slideshow.elapsed += dt; - /* imv->need_redraw = true; /1* need to update display *1/ */ if (imv->slideshow.elapsed >= imv->slideshow.duration) { imv_navigator_select_rel(imv->navigator, 1); imv->slideshow.elapsed = 0; + imv->need_redraw = true; } } @@ -1042,9 +1042,7 @@ int imv_run(struct imv *imv) double timeout = 1.0; /* seconds */ /* If we need to display the next frame of an animation soon we should - * limit our sleep until the next frame is due. If the frame is overdue, - * sleep for 1ms at a time to avoid a glfw race between WaitEvents and - * PostEmptyEvent. + * limit our sleep until the next frame is due. */ if (imv_viewport_is_playing(imv->view) && imv->next_frame.due != 0.0) { timeout = imv->next_frame.due - current_time; @@ -1054,9 +1052,9 @@ int imv_run(struct imv *imv) } if (imv->slideshow.duration > 0) { - double timeleft = imv->slideshow.elapsed - imv->slideshow.duration; + double timeleft = imv->slideshow.duration - imv->slideshow.elapsed; if (timeleft > 0.0 && timeleft < timeout) { - timeout = timeleft + 0.005; + timeout = timeleft + 0.001; } } diff --git a/src/window.c b/src/window.c index 1709468..aed36bd 100644 --- a/src/window.c +++ b/src/window.c @@ -1,10 +1,13 @@ #include "window.h" #include +#include #include #include #include #include +#include +#include #include #include @@ -28,6 +31,9 @@ struct imv_window { EGLSurface egl_surface; struct wl_egl_window *egl_window; + int display_fd; + int event_fd; + int width; int height; bool fullscreen; @@ -266,6 +272,8 @@ static void connect_to_wayland(struct imv_window *window) { window->wl_display = wl_display_connect(NULL); assert(window->wl_display); + window->display_fd = wl_display_get_fd(window->wl_display); + window->event_fd = eventfd(0, 0); window->wl_registry = wl_display_get_registry(window->wl_display); assert(window->wl_registry); @@ -323,6 +331,7 @@ static void create_window(struct imv_window *window, int width, int height, static void shutdown_wayland(struct imv_window *window) { + close(window->event_fd); if (window->wl_pointer) { wl_pointer_destroy(window->wl_pointer); } @@ -405,6 +414,37 @@ void imv_window_resize(struct imv_window *window, int w, int h) void imv_window_wait_for_event(struct imv_window *window, double timeout) { + struct pollfd fds[] = { + {.fd = window->display_fd, .events = POLLIN}, + {.fd = window->event_fd, .events = POLLIN} + }; + nfds_t nfds = sizeof fds / sizeof *fds; + + while (wl_display_prepare_read(window->wl_display)) { + wl_display_dispatch_pending(window->wl_display); + } + + wl_display_flush(window->wl_display); + + int rc = poll(fds, nfds, timeout * 1000); + if (rc < 0) { + wl_display_cancel_read(window->wl_display); + return; + } + + /* Handle any new wayland events */ + if (fds[0].revents & POLLIN) { + wl_display_read_events(window->wl_display); + wl_display_dispatch_pending(window->wl_display); + } else { + wl_display_cancel_read(window->wl_display); + } + + /* Clear the eventfd if hit */ + if (fds[1].revents & POLLIN) { + uint64_t out; + read(window->event_fd, &out, sizeof out); + } } void imv_window_push_event(struct imv_window *window, struct imv_event *e) @@ -420,11 +460,15 @@ void imv_window_push_event(struct imv_window *window, struct imv_event *e) window->events.queue[window->events.len++] = *e; pthread_mutex_unlock(&window->events.mutex); + + /* Wake up wait_events */ + uint64_t in = 1; + write(window->event_fd, &in, sizeof in); } void imv_window_pump_events(struct imv_window *window, imv_event_handler handler, void *data) { - wl_display_dispatch(window->wl_display); + wl_display_dispatch_pending(window->wl_display); pthread_mutex_lock(&window->events.mutex); if (handler) { -- cgit v1.2.3