From 479b155fa1624ccbb3df19d827088c4093b5b6a4 Mon Sep 17 00:00:00 2001 From: 0scar Date: Tue, 15 Aug 2023 09:10:08 +0200 Subject: Move input stuffs into input.{h,c} --- src/input.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) (limited to 'src/input.c') diff --git a/src/input.c b/src/input.c index d53e7ed..633145a 100644 --- a/src/input.c +++ b/src/input.c @@ -1,7 +1,67 @@ #include #include +#include #include +/* Lazy binds, used internally. They are similar to BindAction and friends. + * The only difference is that we set callbacks and such to NULL, but populate + * the function name strings such that can be reloaded. */ +#define BindActionLazy(key, altkey, action_str) \ + (binding_t){\ + .action = (action_t){.action = {\ + .type = InputType_action,\ + .callback = NULL,\ + .callback_str = strdup( action_str ),\ + }},\ + .scancode = key,\ + .scancode_alt = altkey,\ + .since_last_activation = 0\ +} + +#define BindStateLazy(key, altkey, _activate_str , _deactivate_str) \ + (binding_t){\ + .action = (action_t){.state = {\ + .type = InputType_state,\ + .activate = NULL,\ + .deactivate = NULL,\ + .activate_str = strdup( _activate_str ),\ + .deactivate_str = strdup( _deactivate_str ),\ + }},\ + .scancode = key,\ + .scancode_alt = altkey,\ + .since_last_activation = 0\ +} + +void binding_t_free(binding_t* b) { + switch (b->action.type) { + case InputType_error: + ERROR("Cannot free binding of type InputType_error"); + break; + case InputType_action: + free(b->action.action.callback_str); + return; + + case InputType_state: + free(b->action.state.activate_str); + free(b->action.state.deactivate_str); + break; + + case InputType_range: + ERROR("Cannot free binding of type InputType_rage"); + break; + + default: + ERROR("Unknown bindings type"); + break; + } + exit(EXIT_FAILURE); +} + +void i_ctx_t_free(i_ctx* c) { + for (isize i = 0; i < c->len; i++) { + binding_t_free(&c->bindings[i]); + } +} bool binding_action_cmp(binding_t *restrict a, binding_t *restrict b) { InputType t = a->action.type; @@ -92,3 +152,181 @@ action_t i_get_action(const i_ctx *restrict ctx, u32 time, scancode_t scancode) return (action_t){.type = InputType_error}; } + +bool state_refresh_input_ctx(void *lib, i_ctx **ctx, usize ctx_len) { + if (ctx == NULL) return true; + if (ctx_len > 0 && ctx[0] == NULL) return false; + if (lib == NULL) return false; + + for (usize c = 0; c < ctx_len; c++) { + LOG("ctx[%d]->len = %d", c, ctx[c]->len); + for (isize b = 0; b < ctx[c]->len; b++) { + switch (ctx[c]->bindings[b].action.type) { + case InputType_error: + break; + case InputType_action: + if (strcmp("NULL", ctx[c]->bindings[b].action.action.callback_str) != 0) { + + ctx[c]->bindings[b].action.action.callback = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.action.callback_str); + + if (ctx[c]->bindings[b].action.action.callback == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.action.callback_str, + dynamic_library_get_error()); + return false; + } + } + break; + case InputType_state: + if (strcmp("NULL", ctx[c]->bindings[b].action.state.activate_str) != 0) { + + ctx[c]->bindings[b].action.state.activate = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.state.activate_str); + + if (ctx[c]->bindings[b].action.state.activate == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.state.activate_str, + dynamic_library_get_error()); + return false; + } + } + + if (strcmp("NULL", ctx[c]->bindings[b].action.state.deactivate_str) != 0) { + + ctx[c]->bindings[b].action.state.deactivate = + (input_callback_t*)dynamic_library_get_symbol(lib, ctx[c]->bindings[b].action.state.deactivate_str); + + if (ctx[c]->bindings[b].action.state.deactivate == NULL) { + ERROR("Failed to get binding for %s: %s", + ctx[c]->bindings[b].action.state.deactivate_str, + dynamic_library_get_error()); + return false; + } + } + break; + case InputType_range: + default: + break; + } + } + } + + return true; +} + + +/* Make a lazy duplication of a binding. See comments on BindActionLazy and + * friends above. */ +i_ctx* i_ctx_dup(i_ctx **ctx, usize ctx_len) { + usize num_binds = 0; + for (usize c = 0; c < ctx_len; c++) { + num_binds += ctx[c]->len; + } + + binding_t *bb = calloc(num_binds, sizeof(binding_t)); + i_ctx *ret = calloc(ctx_len, sizeof(i_ctx)); + + usize cumsum = 0; + for (usize c = 0; c < ctx_len; c++) { + binding_t *b = ctx[c]->bindings; + ret[c].len = ctx[c]->len; + ret[c].bindings = &bb[cumsum]; + + for (isize i = 0; i < ctx[c]->len; i++) { + switch (b[i].action.type) { + case InputType_error: + break; + case InputType_action: + bb[cumsum] = BindActionLazy( + b[i].scancode, + b[i].scancode_alt, + strdup(b[i].action.action.callback_str)); + break; + case InputType_state: + bb[cumsum] = BindStateLazy( + b[i].scancode, + b[i].scancode_alt, + strdup(b[i].action.state.activate_str), + strdup(b[i].action.state.deactivate_str)); + break; + case InputType_range: + default: + break; + } + cumsum++; + } + } + return ret; +} + +/* Returns a pointer to a binding in c with .action == a. + * Returns NULL if not found. */ +binding_t *get_action(i_ctx *c, action_t *a) { + for (isize i = 0; i < c->len; i++) { + if (c->bindings[i].action.type != a->type) continue; + + switch (c->bindings[i].action) { + case InputType_error: + return NULL; + + case InputType_action: + if (!strcmp(c->bindings[i].action.action.callback_str, a->action.callback_str)) { + return &c->bindings[i]; + } + break; + + case InputType_state: + if (!strcmp(c->bindings[i].action.state.activate_str, a->state.activate_str) + && !strcmp(c->bindings[i].action.state.deactivate_str, a->state.deactivate_str)) { + return &c->bindings[i]; + } + break; + + case InputType_range: + default: + return NULL; + } + } + return NULL; +} + +void i_bind_ctx(i_ctx *c, scancode_t s, action_t *a) { + binding_t* b = get_action(c, a); + + if (b == NULL) { + WARN("Failed to update keybinding"); + return; + } + + b->scancode = s; +} + +void i_bind_ctx_alt(i_ctx *c, scancode_t s, action_t *a) { + binding_t* b = get_action(c, a); + + if (b == NULL) { + WARN("Failed to update keybinding"); + return; + } + + b->scancode_alt = s; +} + +void i_bind(binding_t *b, scancode_t s) { + if (b == NULL) { + WARN("Failed to update keybinding"); + return; + } + + b->scancode = s; +} + +void i_bind_alt(binding_t *b, scancode_t s) { + if (b == NULL) { + WARN("Failed to update keybinding"); + return; + } + + b->scancode_alt = s; +} -- cgit v1.3