summaryrefslogtreecommitdiff
path: root/fakeimp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fakeimp.c')
-rw-r--r--fakeimp.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/fakeimp.c b/fakeimp.c
new file mode 100644
index 0000000..b590450
--- /dev/null
+++ b/fakeimp.c
@@ -0,0 +1,171 @@
+#define _POSIX_C_SOURCE 200809L
+#define _DEFAULT_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wayland-client.h>
+#include <ext-action-binder-v1-protocol.h>
+#include <xcb/xcb.h>
+#include <xcb/xtest.h>
+#include <xcb/xcb_keysyms.h>
+#include <xkbcommon/xkbcommon.h>
+
+struct state;
+struct binding {
+ struct state *state;
+ struct ext_action_binding_v1 *binding;
+ xcb_keycode_t *code;
+};
+
+struct state {
+ struct wl_display *dpy;
+ struct wl_registry *reg;
+ struct ext_action_binder_v1 *binder;
+ struct {
+ size_t len, cap;
+ struct binding *data;
+ } bindings;
+
+ xcb_connection_t *conn;
+ xcb_key_symbols_t *syms;
+};
+
+static void binding_bound(void *data, struct ext_action_binding_v1 *ext_action_binding_v1, const char *trigger) {
+}
+
+static void binding_rejected(void *data, struct ext_action_binding_v1 *ext_action_binding_v1) {
+ (void) data;
+ ext_action_binding_v1_destroy(ext_action_binding_v1);
+}
+
+static void binding_triggered(void *data, struct ext_action_binding_v1 *ext_action_binding_v1, uint32_t time, uint32_t type) {
+ (void) ext_action_binding_v1;
+ struct binding *binding = data;
+ xcb_connection_t *conn = binding->state->conn;
+ switch ((enum ext_action_binding_v1_trigger_type) type) {
+ case EXT_ACTION_BINDING_V1_TRIGGER_TYPE_ONE_SHOT:
+ xcb_request_check(conn,
+ xcb_test_fake_input_checked(conn, XCB_KEY_PRESS, *binding->code, time, XCB_NONE, 0, 0, 0));
+ xcb_request_check(conn,
+ xcb_test_fake_input_checked(conn, XCB_KEY_RELEASE, *binding->code, time, XCB_NONE, 0, 0, 0));
+ break;
+ case EXT_ACTION_BINDING_V1_TRIGGER_TYPE_PRESSED:
+ xcb_request_check(conn,
+ xcb_test_fake_input_checked(conn, XCB_KEY_PRESS, *binding->code, time, XCB_NONE, 0, 0, 0));
+ break;
+ case EXT_ACTION_BINDING_V1_TRIGGER_TYPE_RELEASED:
+ xcb_request_check(conn,
+ xcb_test_fake_input_checked(conn, XCB_KEY_RELEASE, *binding->code, time, XCB_NONE, 0, 0, 0));
+ break;
+ }
+}
+
+static struct ext_action_binding_v1_listener binding_listener = {
+ .bound = binding_bound,
+ .rejected = binding_rejected,
+ .triggered = binding_triggered
+};
+
+static void registry_global(void *data, struct wl_registry *wl_registry,
+ uint32_t name, const char *interface, uint32_t version) {
+ struct state *state = data;
+ (void) version;
+ if (strcmp(interface, ext_action_binder_v1_interface.name) == 0) {
+ state->binder = wl_registry_bind(wl_registry, name, &ext_action_binding_v1_interface, 1);
+ }
+}
+
+static void registry_global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) {
+ (void) data;
+ (void) wl_registry;
+ (void) name;
+}
+
+static struct wl_registry_listener registry_listener = {
+ .global = registry_global,
+ .global_remove = registry_global_remove
+};
+
+static inline struct binding *add_binding(struct state *state, struct binding binding) {
+ if (state->bindings.len + 1 < state->bindings.cap)
+ state->bindings.data = reallocarray(state->bindings.data, state->bindings.cap *= 2, sizeof(*state->bindings.data));
+ state->bindings.data[state->bindings.len] = binding;
+ return &state->bindings.data[state->bindings.len++];
+}
+
+int main(void) {
+ struct state *state = calloc(1, sizeof(*state));
+
+ state->dpy = wl_display_connect(NULL);
+ if (!state->dpy) {
+ fputs("failed to connect to wayland display.\n", stderr);
+ return -1;
+ }
+
+ state->reg = wl_display_get_registry(state->dpy);
+ wl_registry_add_listener(state->reg, &registry_listener, state);
+
+ wl_display_roundtrip(state->dpy);
+
+ if (!state->binder) {
+ fputs("failed to bind to ext-action-binder-v1\n", stderr);
+ return -1;
+ }
+
+ state->conn = xcb_connect(NULL, NULL);
+ if (xcb_connection_has_error(state->conn)) {
+ fputs("failed to open display\n", stderr);
+ return -1;
+ }
+
+ state->syms = xcb_key_symbols_alloc(state->conn);
+
+ FILE *fp = fopen("fakeimp.cfg", "r");
+ if (!fp) {
+ fputs("failed to open config file\n", stderr);
+ return -1;
+ }
+
+ char *line = NULL;
+ size_t n;
+ while (getline(&line, &n, fp) != -1) {
+ char *name = NULL, *namespace = NULL, *keys = NULL;
+ size_t num;
+ if ((num = sscanf(line, "%ms %ms %ms", &name, &namespace, &keys) != 3)) {
+ fprintf(stderr, "failed to parse line %s. %ld\n", line, num);
+ free(name);
+ free(namespace);
+ free(keys);
+ continue;
+ }
+
+ printf("state->binder = %p -- %ld", (void*)state->binder, (intptr_t)state->binder);
+ struct ext_action_binding_v1 *bind = ext_action_binder_v1_create_binding(state->binder);
+ printf("bind = %p -- %ld", (void*)bind, (intptr_t)bind);
+
+ // parse the keybind silly
+ struct binding binding = {
+ .state = state,
+ .binding = ext_action_binder_v1_create_binding(state->binder),
+ .code = xcb_key_symbols_get_keycode(state->syms, 'q')
+ };
+
+ if (!binding.binding) {
+ fputs("binding is null.\n", stderr);
+ return -1;
+ }
+
+ ext_action_binding_v1_set_name(binding.binding, namespace, name);
+ ext_action_binding_v1_add_listener(binding.binding, &binding_listener, add_binding(state, binding));
+ }
+ free(line);
+
+ if (state->bindings.len == 0) {
+ fputs("no bindings set, exiting.\n", stderr);
+ return 0;
+ }
+
+ ext_action_binder_v1_commit(state->binder);
+
+ while (wl_display_dispatch(state->dpy) != -1);
+}