diff --git a/src/config.c b/src/config.c index ea7404d..0db2a47 100644 --- a/src/config.c +++ b/src/config.c @@ -426,7 +426,6 @@ int parse_macro_expression(const char *s, struct macro *macro) macro->sz++; \ } while(0) - char *tok; size_t len = strlen(s); char buf[1024]; diff --git a/src/daemon.c b/src/daemon.c index e2f64d8..cc2cf20 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -403,25 +403,36 @@ static void add_device(struct device *dev) static int event_handler(struct event *ev) { - int timeout; - static struct keyboard *last_kbd = NULL; + static int last_time = 0; + static int timeout = 0; + static struct keyboard *timeout_kbd = NULL; + struct key_event kev; + + timeout -= ev->timestamp - last_time; + last_time = ev->timestamp; + + timeout = timeout < 0 ? 0 : timeout; switch (ev->type) { case EV_TIMEOUT: - if (!last_kbd) + if (!timeout_kbd) return 0; - return kbd_process_key_event(last_kbd, 0, 0); - case EV_DEV_EVENT: - timeout = ev->timeleft; + kev.code = 0; + kev.timestamp = ev->timestamp; + timeout = kbd_process_events(timeout_kbd, &kev, 1); + break; + case EV_DEV_EVENT: if (ev->dev->data) { - last_kbd = ev->dev->data; - + timeout_kbd = ev->dev->data; switch (ev->devev->type) { case DEV_KEY: - timeout = kbd_process_key_event(ev->dev->data, ev->devev->code, - ev->devev->pressed); + kev.code = ev->devev->code; + kev.pressed = ev->devev->pressed; + kev.timestamp = ev->timestamp; + + timeout = kbd_process_events(ev->dev->data, &kev, 1); break; case DEV_MOUSE_MOVE: vkbd_mouse_move(vkbd, ev->devev->x, ev->devev->y); @@ -436,11 +447,15 @@ static int event_handler(struct event *ev) * Treat scroll events as mouse buttons so oneshot and the like get * cleared. */ - if (last_kbd) { - kbd_process_key_event(last_kbd, - KEYD_EXTERNAL_MOUSE_BUTTON, 1); - kbd_process_key_event(last_kbd, - KEYD_EXTERNAL_MOUSE_BUTTON, 0); + if (timeout_kbd) { + kev.code = KEYD_EXTERNAL_MOUSE_BUTTON; + kev.pressed = 1; + kev.timestamp = ev->timestamp; + + kbd_process_events(ev->dev->data, &kev, 1); + + kev.pressed = 0; + timeout = kbd_process_events(ev->dev->data, &kev, 1); } vkbd_mouse_scroll(vkbd, ev->devev->x, ev->devev->y); @@ -448,7 +463,6 @@ static int event_handler(struct event *ev) } } - return timeout; break; case EV_DEV_ADD: if (strcmp(ev->dev->name, VKBD_NAME)) @@ -472,7 +486,7 @@ static int event_handler(struct event *ev) break; } - return 0; + return timeout; } int run_daemon(int argc, char *argv[]) diff --git a/src/evloop.c b/src/evloop.c index be28970..f2d5fbd 100644 --- a/src/evloop.c +++ b/src/evloop.c @@ -74,16 +74,14 @@ int evloop(int (*event_handler) (struct event *ev)) start_time = get_time_ms(); poll(pfds, ndevs+nr_aux_fds+1, timeout > 0 ? timeout : -1); - elapsed = get_time_ms() - start_time; + ev.timestamp = get_time_ms(); + elapsed = ev.timestamp - start_time; - ev.timeleft = timeout; if (timeout > 0 && elapsed >= timeout) { ev.type = EV_TIMEOUT; - ev.timeleft = 0; timeout = event_handler(&ev); } else { timeout -= elapsed; - ev.timeleft = timeout; } for (i = 0; i < ndevs; i++) { diff --git a/src/keyboard.c b/src/keyboard.c index 2c92ad9..241bdc0 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -606,12 +606,14 @@ struct keyboard *new_keyboard(struct config *config, * of kbd_process_key_event must take place. A return value of 0 permits the * main loop to call at liberty. */ -long kbd_process_key_event(struct keyboard *kbd, - uint8_t code, int pressed) +static long process_event(struct keyboard *kbd, uint8_t code, int pressed, int timestamp) { int dl = -1; struct descriptor d; + int timeleft = kbd->timeout - (timestamp - kbd->last_event_ts); + kbd->last_event_ts = timestamp; + /* timeout */ if (!code) { if (kbd->active_macro) { @@ -669,7 +671,31 @@ long kbd_process_key_event(struct keyboard *kbd, cache_set(kbd, code, NULL, -1); } - return process_descriptor(kbd, code, &d, dl, pressed); + kbd->timeout = process_descriptor(kbd, code, &d, dl, pressed); + return kbd->timeout; +} + + +long kbd_process_events(struct keyboard *kbd, const struct key_event *events, size_t n) +{ + size_t i = 0; + int timeout = 0; + int timeout_ts = 0; + + while (i != n) { + const struct key_event *ev = &events[i]; + + if (timeout && timeout_ts < ev->timestamp) { + timeout = process_event(kbd, 0, 0, timeout_ts); + } else { + timeout = process_event(kbd, ev->code, ev->pressed, ev->timestamp); + i++; + } + + timeout_ts = ev->timestamp + timeout; + } + + return timeout; } int kbd_eval(struct keyboard *kbd, const char *exp) diff --git a/src/keyboard.h b/src/keyboard.h index 3f3085c..887e276 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -20,6 +20,12 @@ struct cache_entry { int dl; }; +struct key_event { + uint8_t code; + uint8_t pressed; + int timestamp; +}; + /* May correspond to more than one physical input device. */ struct keyboard { const struct config *original_config; @@ -43,6 +49,8 @@ struct keyboard { int active_macro_layer; long macro_repeat_timeout; + int timeout; + int last_event_ts; struct { long activation_time; @@ -72,7 +80,7 @@ struct keyboard *new_keyboard(struct config *config, void (*sink) (uint8_t code, uint8_t pressed), void (*layer_observer)(struct keyboard *kbd, const char *name, int state)); -long kbd_process_key_event(struct keyboard *kbd, uint8_t code, int pressed); +long kbd_process_events(struct keyboard *kbd, const struct key_event *events, size_t n); int kbd_eval(struct keyboard *kbd, const char *exp); void kbd_reset(struct keyboard *kbd); diff --git a/src/keyd.h b/src/keyd.h index ff3a1ad..59340c9 100644 --- a/src/keyd.h +++ b/src/keyd.h @@ -62,7 +62,7 @@ struct event { enum event_type type; struct device *dev; struct device_event *devev; - int timeleft; + int timestamp; int fd; }; diff --git a/src/monitor.c b/src/monitor.c index 5f445e9..5a43bf1 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -30,17 +30,9 @@ static void cleanup() set_tflags(ICANON|ECHO, 1); } -static long get_time_ms() -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1E3 + ts.tv_nsec / 1E6; -} - int event_handler(struct event *ev) { static long last_time; - long ctime = get_time_ms(); switch (ev->type) { const char *name; @@ -56,17 +48,23 @@ int event_handler(struct event *ev) ev->dev->name, ev->dev->path); break; case EV_DEV_EVENT: - if (ev->devev->type == DEV_KEY) { + switch (ev->devev->type) { + case DEV_KEY: name = keycode_table[ev->devev->code].name; if (time_flag) - printf("+%ld ms\t", ctime - last_time); + printf("+%ld ms\t", ev->timestamp - last_time); printf("%s\t%04x:%04x\t%s %s\n", ev->dev->name, ev->dev->vendor_id, - ev->dev->product_id, name, ev->devev->pressed ? "down" : "up"); - } + ev->dev->product_id, name, + ev->devev->pressed ? "down" : "up"); + + break; + default: + break; + } break; case EV_FD_ERR: exit(0); @@ -78,7 +76,7 @@ int event_handler(struct event *ev) fflush(stdout); fflush(stderr); - last_time = ctime; + last_time = ev->timestamp; return 0; }