diff options
| -rw-r--r-- | dmenu-wl.c | 119 |
1 files changed, 94 insertions, 25 deletions
@@ -6,6 +6,10 @@ #include <xkbcommon/xkbcommon.h> #include <malloc.h> #include <unistd.h> +#include <poll.h> +#include <time.h> +#include <sys/timerfd.h> +#include <errno.h> #include "xdg-shell-protocol.h" #include "dwl-bar-ipc-protocol.h" @@ -39,7 +43,14 @@ typedef struct { uint32_t control; uint32_t alt; uint32_t shift; - } mod; + uint32_t sym; + uint32_t state; + } keys; + struct { + int timer; + int delay; + int period; + } repeat; } Client; typedef struct Monitor Monitor; @@ -87,6 +98,7 @@ static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t f static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state); static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay); +static void handle_keyboard_event(); static void dummy() {} /* global variables */ @@ -329,15 +341,56 @@ keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32 void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { - int genmatch = 0; - char buf[128]; + struct itimerspec spec = { 0 }; uint32_t keycode = key + 8; xkb_keysym_t sym = xkb_state_key_get_one_sym(client.xkb_state, keycode); - xkb_keysym_get_name(sym, buf, sizeof(buf)); - xkb_state_key_get_utf8(client.xkb_state, keycode, buf, sizeof(buf)); + client.keys.sym = sym; + client.keys.state = state; + handle_keyboard_event(); + + + if (client.keys.state == WL_KEYBOARD_KEY_STATE_PRESSED && client.repeat.period >= 0) { + spec.it_value.tv_sec = client.repeat.delay / 1000; + spec.it_value.tv_nsec = (client.repeat.delay % 1000) * 1000000; + timerfd_settime(client.repeat.timer, 0, &spec, 0); + } else if (client.keys.state == WL_KEYBOARD_KEY_STATE_RELEASED) { + timerfd_settime(client.repeat.timer, 0, &spec, 0); + } +} + + +void +keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) +{ + xkb_state_update_mask(client.xkb_state, depressed, latched, locked, 0, 0, group); + client.keys.alt = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + client.keys.control = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + client.keys.shift = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); +} + + +void +keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay) +{ + client.repeat.delay = delay; + + if (rate > 0) + client.repeat.period = 1000 / rate; + else + client.repeat.period = -1; +} + + +void +handle_keyboard_event() +{ + char buf[8]; + int genmatch = 0; - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - switch (sym) { + xkb_keysym_to_utf8(client.keys.sym, buf, sizeof(buf)); + + if (client.keys.state == WL_KEYBOARD_KEY_STATE_PRESSED) { + switch (client.keys.sym) { case XKB_KEY_KP_Enter: /* fallthrough */ case XKB_KEY_Return: fputs(options.selection ? options.selection->name: input_field, stdout); @@ -366,23 +419,6 @@ keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t void -keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) -{ - xkb_state_update_mask(client.xkb_state, depressed, latched, locked, 0, 0, group); - client.mod.alt = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); - client.mod.control = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); - client.mod.shift = xkb_state_mod_name_is_active(client.xkb_state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); -} - - -void -keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay) -{ - /* TODO */ -} - - -void readstdin() { unsigned s; @@ -431,6 +467,7 @@ setup() generate_matches(); height = (lines + 1) * (fontsize + padding * 2) + 3 * borderwidth; + client.repeat.timer = timerfd_create(CLOCK_MONOTONIC, 0); client.xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); client.display = wl_display_connect(0); client.registry = wl_display_get_registry(client.display); @@ -465,10 +502,42 @@ setup() int main(int argc, char *argv[]) { + struct itimerspec spec = { 0 }; + struct pollfd fds[2]; + readstdin(); setup(); - while (running && wl_display_dispatch(client.display)) { + fds[0].fd = wl_display_get_fd(client.display); + fds[0].events = POLLIN; + fds[1].fd = client.repeat.timer; + fds[1].events = POLLIN; + + while (running) { + if (wl_display_flush(client.display) < 0) { + if (errno == EAGAIN) + continue; + break; + } + + if (poll(fds, sizeof(fds) / sizeof(*fds), -1) < 0) { + if (errno == EAGAIN) + continue; + break; + } + + if (fds[0].revents & POLLIN) { + if (wl_display_dispatch(client.display) < 0) { + running = 0; + } + } + + if (fds[1].revents & POLLIN) { + handle_keyboard_event(); + spec.it_value.tv_sec = client.repeat.period / 1000; + spec.it_value.tv_nsec = (client.repeat.period % 1000) * 1000000; + timerfd_settime(client.repeat.timer, 0, &spec, 0); + } } wl_display_dispatch(client.display); |