From 917b359b1934aea7e4dbade51b22272b26997152 Mon Sep 17 00:00:00 2001 From: "Anna (navi) Figueiredo Gomes" Date: Sun, 3 Mar 2024 22:01:27 +0100 Subject: initial Signed-off-by: Anna (navi) Figueiredo Gomes --- fakeimp.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fakeimp.cfg | 1 + meson.build | 38 ++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 fakeimp.c create mode 100644 fakeimp.cfg create mode 100644 meson.build 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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, ®istry_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); +} diff --git a/fakeimp.cfg b/fakeimp.cfg new file mode 100644 index 0000000..af3b6d7 --- /dev/null +++ b/fakeimp.cfg @@ -0,0 +1 @@ +discord mute q diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..7b33b3a --- /dev/null +++ b/meson.build @@ -0,0 +1,38 @@ +project('fakeimp', 'c', + version : '0.1', + default_options : ['warning_level=3', 'c_std=c2x']) + +sources = [ + 'fakeimp.c' +] + +wl_protocols = dependency('wayland-protocols').get_variable('pkgdatadir') +wl_scanner = find_program(dependency('wayland-scanner').get_variable('wayland_scanner')) + +protos = { + 'ext-action-binder': wl_protocols / 'staging/ext-action-binder/ext-action-binder-v1.xml' +} + +foreach name, path : protos + sources += custom_target( + name.underscorify() + '_c', + input: path, + output: '@BASENAME@-protocol.c', + command: [wl_scanner, 'private-code', '@INPUT@', '@OUTPUT@'] + ) + sources += custom_target( + name.underscorify() + '_h', + input: path, + output: '@BASENAME@-protocol.h', + command: [wl_scanner, 'client-header', '@INPUT@', '@OUTPUT@'] + ) +endforeach + +exe = executable('fakeimp', sources, + dependencies: [ + dependency('wayland-client'), + dependency('xcb'), + dependency('xcb-keysyms'), + dependency('xcb-xtest') + ], + install : true) -- cgit v1.2.3