diff --git a/meson.build b/meson.build index 47f051b..9fc9633 100644 --- a/meson.build +++ b/meson.build @@ -98,8 +98,12 @@ if build_wayland dependency('wayland-cursor'), dependency('wayland-egl'), dependency('egl'), - cc.find_library('rt'), ] + if host_machine.system() != 'linux' + # Linux has natively; elsewhere (e.g. macOS/BSD) it's + # provided by epoll-shim, which also exposes struct itimerspec there. + deps_for_wayland += dependency('epoll-shim') + endif wl_protos = dependency('wayland-protocols') wl_scanner = find_program('wayland-scanner', native: true) diff --git a/src/wl_window.c b/src/wl_window.c index 8576500..0f20e2f 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -8,10 +8,11 @@ #include #include #include -#include #include #include +#include #include +#include #include #include @@ -50,7 +51,7 @@ struct imv_window { int display_fd; int pipe_fds[2]; - timer_t timer_id; + int timer_fd; int repeat_scancode; /* scancode of key to repeat */ int repeat_delay; /* time before repeat in ms */ int repeat_interval; /* time between repeats in ms */ @@ -253,7 +254,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard, .tv_nsec = 0, }, }; - timer_settime(window->timer_id, 0, &off, NULL); + timerfd_settime(window->timer_fd, 0, &off, NULL); return; } @@ -274,7 +275,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard, .tv_nsec = window->repeat_interval * 1000 * 1000, }, }; - timer_settime(window->timer_id, 0, &period, NULL); + timerfd_settime(window->timer_fd, 0, &period, NULL); } } @@ -978,9 +979,10 @@ static void shutdown_wayland(struct imv_window *window) } } -static void on_timer(union sigval sigval) +static void handle_repeat_timer(struct imv_window *window) { - struct imv_window *window = sigval.sival_ptr; + uint64_t expirations; + read(window->timer_fd, &expirations, sizeof expirations); push_keypress(window, window->repeat_scancode); } @@ -1010,19 +1012,14 @@ struct imv_window *imv_window_create(int width, int height, const char *title, create_window(window, width, height, title, app_id); load_gl_functions(); - struct sigevent timer_handler = { - .sigev_notify = SIGEV_THREAD, - .sigev_value.sival_ptr = window, - .sigev_notify_function = on_timer, - }; - int timer_rc = timer_create(CLOCK_MONOTONIC, &timer_handler, &window->timer_id); - assert(timer_rc == 0); + window->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); + assert(window->timer_fd != -1); return window; } void imv_window_free(struct imv_window *window) { - timer_delete(window->timer_id); + close(window->timer_fd); imv_keyboard_free(window->keyboard); shutdown_wayland(window); list_deep_free(window->wl_outputs); @@ -1109,7 +1106,8 @@ void imv_window_wait_for_event(struct imv_window *window, double timeout) { struct pollfd fds[] = { {.fd = window->display_fd, .events = POLLIN}, - {.fd = window->pipe_fds[0], .events = POLLIN} + {.fd = window->pipe_fds[0], .events = POLLIN}, + {.fd = window->timer_fd, .events = POLLIN}, }; nfds_t nfds = sizeof fds / sizeof *fds; @@ -1133,6 +1131,10 @@ void imv_window_wait_for_event(struct imv_window *window, double timeout) } else { wl_display_cancel_read(window->wl_display); } + + if (fds[2].revents & POLLIN) { + handle_repeat_timer(window); + } } void imv_window_push_event(struct imv_window *window, struct imv_event *e)