diff options
Diffstat (limited to 'rust/qmk-hid-com/src_c/src/keyboard/keyboard.c')
-rw-r--r-- | rust/qmk-hid-com/src_c/src/keyboard/keyboard.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c new file mode 100644 index 0000000..4949085 --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c @@ -0,0 +1,135 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "virtual-keyboard-unstable-v1-client-protocol.h" + +#include "../error.h" +#include "keyboard.h" + + +static void handle_wl_event(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version); +static void handle_wl_event_remove(void *data, struct wl_registry *registry, + uint32_t name); + +const struct wl_registry_listener registry_listener = { + .global = handle_wl_event, + .global_remove = handle_wl_event_remove, +}; + +struct qmk_unicode_type init_qmk_unicode() { + struct qmk_unicode_type qmk_unicode_type; + + memset(&qmk_unicode_type, 0, sizeof(qmk_unicode_type)); + qmk_unicode_type.display = wl_display_connect(NULL); + + if (qmk_unicode_type.display == NULL) { + fail("Wayland connection failed"); + } + + qmk_unicode_type.registry = wl_display_get_registry(qmk_unicode_type.display); + + wl_registry_add_listener(qmk_unicode_type.registry, ®istry_listener, + &qmk_unicode_type); + wl_display_dispatch(qmk_unicode_type.display); + wl_display_roundtrip(qmk_unicode_type.display); + + if (qmk_unicode_type.manager == NULL) { + fail("Compositor does not support the virtual keyboard protocol"); + } + if (qmk_unicode_type.seat == NULL) { + fail("No seat found"); + } + + qmk_unicode_type.keyboard = + zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( + qmk_unicode_type.manager, qmk_unicode_type.seat); + + return qmk_unicode_type; +} +void destroy_qmk_unicode(struct qmk_unicode_type qmk_unicode_type) { + zwp_virtual_keyboard_v1_destroy(qmk_unicode_type.keyboard); + zwp_virtual_keyboard_manager_v1_destroy(qmk_unicode_type.manager); + wl_registry_destroy(qmk_unicode_type.registry); + wl_display_disconnect(qmk_unicode_type.display); +} + +static void upload_keymap(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code); + +void type_keycode(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code) { + upload_keymap(qmk_unicode_type, key_code); + + zwp_virtual_keyboard_v1_key(qmk_unicode_type->keyboard, 0, 1, + WL_KEYBOARD_KEY_STATE_PRESSED); + wl_display_roundtrip(qmk_unicode_type->display); + usleep(2000); + zwp_virtual_keyboard_v1_key(qmk_unicode_type->keyboard, 0, 1, + WL_KEYBOARD_KEY_STATE_RELEASED); + wl_display_roundtrip(qmk_unicode_type->display); + usleep(2000); +} + +static void handle_wl_event(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version) { + struct qmk_unicode_type *qmk_unicode_type = (struct qmk_unicode_type *)data; + + if (!strcmp(interface, wl_seat_interface.name)) { + qmk_unicode_type->seat = (struct wl_seat *)wl_registry_bind( + registry, name, &wl_seat_interface, version <= 7 ? version : 7); + } else if (!strcmp(interface, + zwp_virtual_keyboard_manager_v1_interface.name)) { + qmk_unicode_type->manager = + (struct zwp_virtual_keyboard_manager_v1 *)wl_registry_bind( + registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); + } +} + +static void +handle_wl_event_remove(__attribute__((unused)) void *data, + __attribute__((unused)) struct wl_registry *_registry, + __attribute__((unused)) uint32_t _name) {} + +static void upload_keymap(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code) { + char filename[] = "/tmp/qmk_unicode_type-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) { + fail("Failed to create the temporary keymap file"); + } + unlink(filename); + FILE *f = fdopen(fd, "w"); + + fprintf(f, + "xkb_keymap {\n" + " xkb_keycodes \"(unnamed)\" {\n" + " minimum = 8;\n" + " maximum = 10;\n" + " <K1> = 9;\n" + " };\n" + // TODO: Is including "complete" here really a good idea? + " xkb_types \"(unnamed)\" { include \"complete\" };\n" + " xkb_compatibility \"(unnamed)\" { include \"complete\" };\n" + " xkb_symbols \"(unnamed)\" {\n" + " key <K1> {[U%X]};\n" + " };\n" + "};\n", + key_code); + + fputc('\0', f); + fflush(f); + + uint32_t keymap_size = (uint32_t)ftell(f); + zwp_virtual_keyboard_v1_keymap(qmk_unicode_type->keyboard, + WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fileno(f), + keymap_size); + + wl_display_roundtrip(qmk_unicode_type->display); + fclose(f); +} |