aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/keyboard.c81
1 files changed, 66 insertions, 15 deletions
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
index 003aab98..84e5213c 100644
--- a/rootston/keyboard.c
+++ b/rootston/keyboard.c
@@ -10,36 +10,87 @@
#include <xkbcommon/xkbcommon.h>
#include "rootston/input.h"
-static void keyboard_key_notify(struct wl_listener *listener, void *data) {
- struct wlr_event_keyboard_key *event = data;
- struct roots_keyboard *keyboard = wl_container_of(listener, keyboard, key);
- struct roots_input *input = keyboard->input;
- struct roots_server *server = input->server;
+static ssize_t keyboard_pressed_key_index(struct roots_keyboard *keyboard,
+ uint32_t keycode) {
+ for (size_t i = 0; i < ROOTS_KEYBOARD_PRESSED_KEYS_CAP; i++) {
+ if (keyboard->pressed_keys[i].keycode == keycode) {
+ return i;
+ }
+ }
+ return -1;
+}
- enum wlr_key_state key_state = event->state;
- uint32_t keycode = event->keycode + 8;
- const xkb_keysym_t *syms;
- int nsyms = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
- keycode, &syms);
- for (int i = 0; i < nsyms; ++i) {
- xkb_keysym_t sym = syms[i];
+static void keyboard_key_press(struct roots_keyboard *keyboard,
+ struct roots_keyboard_key *key) {
+ struct roots_server *server = keyboard->input->server;
+
+ ssize_t i = keyboard_pressed_key_index(keyboard, key->keycode);
+ if (i < 0) {
+ i = keyboard_pressed_key_index(keyboard, 0);
+ if (i >= 0) {
+ memcpy(&keyboard->pressed_keys[i], key,
+ sizeof(struct roots_keyboard_key));
+ }
+ }
+
+ for (size_t i = 0; i < key->syms_len; i++) {
+ xkb_keysym_t sym = key->syms[i];
if (sym == XKB_KEY_Escape) {
// TEMPORARY, probably
wl_display_terminate(server->wl_display);
- } else if (key_state == WLR_KEY_PRESSED &&
- sym >= XKB_KEY_XF86Switch_VT_1 &&
+ } else if (sym >= XKB_KEY_XF86Switch_VT_1 &&
sym <= XKB_KEY_XF86Switch_VT_12) {
if (wlr_backend_is_multi(server->backend)) {
struct wlr_session *session =
wlr_multi_get_session(server->backend);
if (session) {
- wlr_session_change_vt(session, sym - XKB_KEY_XF86Switch_VT_1 + 1);
+ unsigned vt = sym - XKB_KEY_XF86Switch_VT_1 + 1;
+ wlr_session_change_vt(session, vt);
}
}
}
}
}
+static void keyboard_key_release(struct roots_keyboard *keyboard,
+ struct roots_keyboard_key *key) {
+ ssize_t i = keyboard_pressed_key_index(keyboard, key->keycode);
+ if (i >= 0) {
+ struct roots_keyboard_key *pressed_key = &keyboard->pressed_keys[i];
+ memset(pressed_key, 0, sizeof(struct roots_keyboard_key));
+ }
+}
+
+static void keyboard_key_notify(struct wl_listener *listener, void *data) {
+ struct wlr_event_keyboard_key *event = data;
+ struct roots_keyboard *keyboard = wl_container_of(listener, keyboard, key);
+
+ uint32_t keycode = event->keycode + 8;
+ const xkb_keysym_t *syms;
+ int syms_len = xkb_state_key_get_syms(keyboard->device->keyboard->xkb_state,
+ keycode, &syms);
+
+ struct roots_keyboard_key *key = calloc(1,
+ sizeof(struct roots_keyboard_key));
+ if (key == NULL) {
+ return;
+ }
+ key->keycode = keycode;
+ key->syms = syms;
+ key->syms_len = syms_len;
+
+ switch (event->state) {
+ case WLR_KEY_PRESSED:
+ keyboard_key_press(keyboard, key);
+ break;
+ case WLR_KEY_RELEASED:
+ keyboard_key_release(keyboard, key);
+ break;
+ }
+
+ free(key);
+}
+
void keyboard_add(struct wlr_input_device *device, struct roots_input *input) {
struct roots_keyboard *keyboard = calloc(sizeof(struct roots_keyboard), 1);
device->data = keyboard;