summaryrefslogtreecommitdiff
path: root/dmenu-wl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmenu-wl.c')
-rw-r--r--dmenu-wl.c119
1 files changed, 94 insertions, 25 deletions
diff --git a/dmenu-wl.c b/dmenu-wl.c
index 3cc5a05..9debd69 100644
--- a/dmenu-wl.c
+++ b/dmenu-wl.c
@@ -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);