aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHarry Jeffery <harry@exec64.co.uk>2019-07-12 23:32:44 +0100
committerHarry Jeffery <harry@exec64.co.uk>2019-07-12 23:32:44 +0100
commit311623d4c14c59db1ebdf87c372baf601226398e (patch)
tree33d183cf4ec2f4d7f63c77b31583ee8c549c2726 /src
parent88f7be23b0d3d6e69ad8d99f22c567c022564e18 (diff)
downloadimv-311623d4c14c59db1ebdf87c372baf601226398e.tar.gz
Modernise event loop
Diffstat (limited to 'src')
-rw-r--r--src/imv.c10
-rw-r--r--src/window.c46
2 files changed, 49 insertions, 7 deletions
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 <assert.h>
+#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
#include <wayland-client.h>
#include <wayland-egl.h>
@@ -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) {