#include <cairo.h>
#include <math.h>
#include <assert.h>
-#include <sys/timerfd.h>
-#include <sys/epoll.h>
#include <unistd.h>
+#include <time.h>
#include <linux/input.h>
#include <wayland-client.h>
int reset;
struct input *cursor_timeout_input;
- int cursor_timeout_fd;
- struct task cursor_timeout_task;
+ struct toytimer cursor_timeout;
};
static void
static void
cursor_timeout_reset(struct clickdot *clickdot)
{
- const long cursor_timeout = 500;
- struct itimerspec its;
-
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 0;
- its.it_value.tv_sec = cursor_timeout / 1000;
- its.it_value.tv_nsec = (cursor_timeout % 1000) * 1000 * 1000;
- timerfd_settime(clickdot->cursor_timeout_fd, 0, &its, NULL);
+ toytimer_arm_once_usec(&clickdot->cursor_timeout, 500 * 1000);
}
static int
}
static void
-cursor_timeout_func(struct task *task, uint32_t events)
+cursor_timeout_func(struct toytimer *tt)
{
struct clickdot *clickdot =
- container_of(task, struct clickdot, cursor_timeout_task);
- uint64_t exp;
-
- if (read(clickdot->cursor_timeout_fd, &exp, sizeof (uint64_t)) !=
- sizeof(uint64_t))
- abort();
+ container_of(tt, struct clickdot, cursor_timeout);
input_set_pointer_image(clickdot->cursor_timeout_input,
CURSOR_LEFT_PTR);
clickdot->line.old_y = -1;
clickdot->reset = 0;
- clickdot->cursor_timeout_fd =
- timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
- clickdot->cursor_timeout_task.run = cursor_timeout_func;
- display_watch_fd(window_get_display(clickdot->window),
- clickdot->cursor_timeout_fd,
- EPOLLIN, &clickdot->cursor_timeout_task);
+ toytimer_init(&clickdot->cursor_timeout, CLOCK_MONOTONIC,
+ display, cursor_timeout_func);
return clickdot;
}
static void
clickdot_destroy(struct clickdot *clickdot)
{
- display_unwatch_fd(window_get_display(clickdot->window),
- clickdot->cursor_timeout_fd);
- close(clickdot->cursor_timeout_fd);
+ toytimer_fini(&clickdot->cursor_timeout);
if (clickdot->buffer)
cairo_surface_destroy(clickdot->buffer);
widget_destroy(clickdot->widget);
struct wl_callback *cursor_frame_cb;
uint32_t cursor_timer_start;
uint32_t cursor_anim_current;
- int cursor_delay_fd;
+ struct toytimer cursor_timer;
bool cursor_timer_running;
- struct task cursor_task;
struct wl_surface *pointer_surface;
uint32_t modifiers;
uint32_t pointer_enter_serial;
struct widget *parent;
struct widget *widget;
char *entry;
- struct task tooltip_task;
- int tooltip_fd;
+ struct toytimer timer;
float x, y;
};
tooltip->widget = NULL;
}
- close(tooltip->tooltip_fd);
+ toytimer_fini(&tooltip->timer);
free(tooltip->entry);
free(tooltip);
parent->tooltip = NULL;
}
static void
-tooltip_func(struct task *task, uint32_t events)
+tooltip_func(struct toytimer *tt)
{
- struct tooltip *tooltip =
- container_of(task, struct tooltip, tooltip_task);
- uint64_t exp;
+ struct tooltip *tooltip = container_of(tt, struct tooltip, timer);
- if (read(tooltip->tooltip_fd, &exp, sizeof (uint64_t)) != sizeof (uint64_t))
- abort();
window_create_tooltip(tooltip);
}
static int
tooltip_timer_reset(struct tooltip *tooltip)
{
- struct itimerspec its;
-
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 0;
- its.it_value.tv_sec = TOOLTIP_TIMEOUT / 1000;
- its.it_value.tv_nsec = (TOOLTIP_TIMEOUT % 1000) * 1000 * 1000;
- if (timerfd_settime(tooltip->tooltip_fd, 0, &its, NULL) < 0) {
- fprintf(stderr, "could not set timerfd\n: %m");
- return -1;
- }
+ toytimer_arm_once_usec(&tooltip->timer, TOOLTIP_TIMEOUT * 1000);
return 0;
}
tooltip->x = x;
tooltip->y = y;
tooltip->entry = strdup(entry);
- tooltip->tooltip_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
- if (tooltip->tooltip_fd < 0) {
- fprintf(stderr, "could not create timerfd\n: %m");
- return -1;
- }
-
- tooltip->tooltip_task.run = tooltip_func;
- display_watch_fd(parent->window->display, tooltip->tooltip_fd,
- EPOLLIN, &tooltip->tooltip_task);
+ toytimer_init(&tooltip->timer, CLOCK_MONOTONIC,
+ parent->window->display, tooltip_func);
tooltip_timer_reset(tooltip);
return 0;
static void
cursor_delay_timer_reset(struct input *input, uint32_t duration)
{
- struct itimerspec its;
-
if (!duration)
input->cursor_timer_running = false;
else
input->cursor_timer_running = true;
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 0;
- its.it_value.tv_sec = duration / 1000;
- its.it_value.tv_nsec = (duration % 1000) * 1000 * 1000;
- if (timerfd_settime(input->cursor_delay_fd, 0, &its, NULL) < 0)
- fprintf(stderr, "could not set cursor timerfd\n: %m");
+ toytimer_arm_once_usec(&input->cursor_timer, duration * 1000);
}
static void cancel_pointer_image_update(struct input *input)
}
static void
-cursor_timer_func(struct task *task, uint32_t events)
+cursor_timer_func(struct toytimer *tt)
{
- struct input *input = container_of(task, struct input, cursor_task);
+ struct input *input = container_of(tt, struct input, cursor_timer);
struct timespec tp;
struct wl_cursor *cursor;
uint32_t time;
- uint64_t exp;
if (!input->cursor_timer_running)
return;
- if (read(input->cursor_delay_fd, &exp, sizeof (uint64_t)) != sizeof (uint64_t))
- return;
-
cursor = input->display->cursors[input->current_cursor];
if (!cursor)
return;
}
input->pointer_surface = wl_compositor_create_surface(d->compositor);
- input->cursor_task.run = cursor_timer_func;
- input->cursor_delay_fd = timerfd_create(CLOCK_MONOTONIC,
- TFD_CLOEXEC | TFD_NONBLOCK);
- display_watch_fd(d, input->cursor_delay_fd, EPOLLIN,
- &input->cursor_task);
+ toytimer_init(&input->cursor_timer, CLOCK_MONOTONIC, d,
+ cursor_timer_func);
set_repeat_info(input, 40, 400);
input->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC,
wl_list_remove(&input->link);
wl_seat_destroy(input->seat);
close(input->repeat_timer_fd);
- close(input->cursor_delay_fd);
+ toytimer_fini(&input->cursor_timer);
free(input);
}
return 1 << index;
}
+
+static void
+toytimer_fire(struct task *tsk, uint32_t events)
+{
+ uint64_t e;
+ struct toytimer *tt;
+
+ tt = container_of(tsk, struct toytimer, tsk);
+
+ if (events != EPOLLIN)
+ fprintf(stderr, "unexpected timerfd events %x\n", events);
+
+ if (!(events & EPOLLIN))
+ return;
+
+ if (read(tt->fd, &e, sizeof e) != sizeof e) {
+ /* If we change the timer between the fd becoming
+ * readable and getting here, there'll be nothing to
+ * read and we get EAGAIN. */
+ if (errno != EAGAIN)
+ fprintf(stderr, "timer read failed: %m\n");
+ return;
+ }
+
+ tt->callback(tt);
+}
+
+void
+toytimer_init(struct toytimer *tt, clockid_t clock, struct display *display,
+ toytimer_cb callback)
+{
+ memset(tt, 0, sizeof *tt);
+
+ tt->fd = timerfd_create(clock, TFD_CLOEXEC | TFD_NONBLOCK);
+ if (tt->fd == -1) {
+ fprintf(stderr, "creating timer failed: %m\n");
+ abort();
+ }
+
+ tt->display = display;
+ tt->callback = callback;
+ tt->tsk.run = toytimer_fire;
+ display_watch_fd(display, tt->fd, EPOLLIN, &tt->tsk);
+}
+
+void
+toytimer_fini(struct toytimer *tt)
+{
+ display_unwatch_fd(tt->display, tt->fd);
+ close(tt->fd);
+ tt->fd = -1;
+}
+
+void
+toytimer_arm(struct toytimer *tt, const struct itimerspec *its)
+{
+ int ret;
+
+ ret = timerfd_settime(tt->fd, 0, its, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "timer setup failed: %m\n");
+ abort();
+ }
+}
+
+#define USEC_PER_SEC 1000000
+
+void
+toytimer_arm_once_usec(struct toytimer *tt, uint32_t usec)
+{
+ struct itimerspec its;
+
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+ its.it_value.tv_sec = usec / USEC_PER_SEC;
+ its.it_value.tv_nsec = (usec % USEC_PER_SEC) * 1000;
+ toytimer_arm(tt, &its);
+}
+
+void
+toytimer_disarm(struct toytimer *tt)
+{
+ struct itimerspec its = {};
+
+ toytimer_arm(tt, &its);
+}