uint16_t code,
int32_t value)
{
- int ret;
-
if (type != EV_KEY)
return;
- ret = uxkb_dev_process(dev, value, code);
- if (ret)
- return;
-
- shl_hook_call(dev->input->hook, dev->input, &dev->event);
+ uxkb_dev_process(dev, value, code);
}
static void input_data_dev(struct ev_fd *fd, int mask, void *data)
dev->input = input;
dev->rfd = -1;
dev->features = features;
+ dev->repeat_rate = 25;
+ dev->repeat_delay = 250;
dev->node = strdup(node);
if (!dev->node)
dev->event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
if (!dev->event.codepoints)
goto err_syms;
+ dev->repeat_event.keysyms = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->repeat_event.keysyms)
+ goto err_codepoints;
+ dev->repeat_event.codepoints = malloc(sizeof(uint32_t) * dev->num_syms);
+ if (!dev->repeat_event.codepoints)
+ goto err_rsyms;
ret = uxkb_dev_init(dev);
if (ret)
- goto err_codepoints;
+ goto err_rcodepoints;
if (input->awake > 0) {
ret = input_wake_up_dev(dev);
err_kbd:
uxkb_dev_destroy(dev);
+err_rcodepoints:
+ free(dev->repeat_event.codepoints);
+err_rsyms:
+ free(dev->repeat_event.keysyms);
err_codepoints:
free(dev->event.codepoints);
err_syms:
input_sleep_dev(dev);
shl_dlist_unlink(&dev->list);
uxkb_dev_destroy(dev);
+ free(dev->repeat_event.codepoints);
+ free(dev->repeat_event.keysyms);
free(dev->event.codepoints);
free(dev->event.keysyms);
free(dev->node);
#include <string.h>
#include <xkbcommon/xkbcommon.h>
#include "log.h"
+#include "shl_hook.h"
#include "shl_misc.h"
#include "uterm.h"
#include "uterm_input.h"
xkb_context_unref(input->ctx);
}
+static void timer_event(struct ev_timer *timer, uint64_t num, void *data)
+{
+ struct uterm_input_dev *dev = data;
+
+ dev->repeat_event.handled = false;
+ shl_hook_call(dev->input->hook, dev->input, &dev->repeat_event);
+}
+
int uxkb_dev_init(struct uterm_input_dev *dev)
{
+ int ret;
+
+ ret = ev_eloop_new_timer(dev->input->eloop, &dev->repeat_timer, NULL,
+ timer_event, dev);
+ if (ret)
+ return ret;
+
dev->state = xkb_state_new(dev->input->keymap);
- if (!dev->state)
- return -ENOMEM;
+ if (!dev->state) {
+ log_error("cannot create XKB state");
+ ret = -ENOMEM;
+ goto err_timer;
+ }
return 0;
+
+err_timer:
+ ev_eloop_rm_timer(dev->repeat_timer);
+ return ret;
}
void uxkb_dev_destroy(struct uterm_input_dev *dev)
{
xkb_state_unref(dev->state);
+ ev_eloop_rm_timer(dev->repeat_timer);
}
#define EVDEV_KEYCODE_OFFSET 8
const xkb_keysym_t *keysyms;
int num_keysyms, i;
uint32_t *tmp;
+ struct itimerspec spec;
+
+ if (key_state == KEY_REPEATED)
+ return -ENOKEY;
state = dev->state;
keymap = xkb_state_get_map(state);
else if (key_state == KEY_RELEASED)
xkb_state_update_key(state, keycode, XKB_KEY_UP);
- if (key_state == KEY_RELEASED)
- return -ENOKEY;
-
- if (key_state == KEY_REPEATED && !xkb_key_repeats(keymap, keycode))
- return -ENOKEY;
-
if (num_keysyms <= 0)
return -ENOKEY;
}
dev->event.codepoints = tmp;
+ tmp = realloc(dev->repeat_event.keysyms,
+ sizeof(uint32_t) * num_keysyms);
+ if (!tmp) {
+ log_warning("cannot reallocate keysym buffer");
+ return -ENOKEY;
+ }
+ dev->repeat_event.keysyms = tmp;
+
+ tmp = realloc(dev->repeat_event.codepoints,
+ sizeof(uint32_t) * num_keysyms);
+ if (!tmp) {
+ log_warning("cannot reallocate codepoints buffer");
+ return -ENOKEY;
+ }
+ dev->repeat_event.codepoints = tmp;
+
dev->num_syms = num_keysyms;
}
dev->event.codepoints[i] = UTERM_INPUT_INVALID;
}
+ if (key_state == KEY_RELEASED &&
+ dev->repeat_event.num_syms == num_keysyms &&
+ !memcmp(dev->repeat_event.keysyms,
+ keysyms,
+ sizeof(uint32_t) * num_keysyms)) {
+ ev_timer_update(dev->repeat_timer, NULL);
+ } else if (key_state == KEY_PRESSED &&
+ xkb_key_repeats(keymap, keycode)) {
+ dev->repeat_event.keycode = code;
+ dev->repeat_event.ascii = dev->event.ascii;
+ dev->repeat_event.mods = dev->event.mods;
+ dev->repeat_event.num_syms = num_keysyms;
+
+ for (i = 0; i < num_keysyms; ++i) {
+ dev->repeat_event.keysyms[i] = dev->event.keysyms[i];
+ dev->repeat_event.codepoints[i] =
+ dev->event.codepoints[i];
+ }
+
+ spec.it_interval.tv_sec = 0;
+ spec.it_interval.tv_nsec = dev->repeat_rate * 1000000;
+ spec.it_value.tv_sec = 0;
+ spec.it_value.tv_nsec = dev->repeat_delay * 1000000;
+ ev_timer_update(dev->repeat_timer, &spec);
+ }
+
+ if (key_state == KEY_RELEASED)
+ return -ENOKEY;
+
+ shl_hook_call(dev->input->hook, dev->input, &dev->event);
+
return 0;
}