From 3d3400b495067392fa7675dc326f48dcebeb12f8 Mon Sep 17 00:00:00 2001 From: onelin Date: Wed, 26 Mar 2025 18:44:31 +0100 Subject: Use keycodes instead of scancodes --- src/ctrl/include/engine/ctrl/input.h | 28 ++++---- src/ctrl/include/engine/ctrl/keycodes.h | 93 ++++++++++++++++++++++++++ src/ctrl/include/engine/ctrl/scancodes.h | 110 +++++++++++++++---------------- src/ctrl/src/input.c | 95 ++++++++++++++++---------- 4 files changed, 225 insertions(+), 101 deletions(-) create mode 100644 src/ctrl/include/engine/ctrl/keycodes.h (limited to 'src/ctrl') diff --git a/src/ctrl/include/engine/ctrl/input.h b/src/ctrl/include/engine/ctrl/input.h index c8dc56b..8ed77b4 100644 --- a/src/ctrl/include/engine/ctrl/input.h +++ b/src/ctrl/include/engine/ctrl/input.h @@ -6,10 +6,12 @@ extern "C" { #endif #include -#include +//#include +#include typedef void input_callback_t(void*); typedef i32 scancode_t; +typedef i32 keycode_t; typedef enum InputType { InputType_error = 0, @@ -40,22 +42,22 @@ typedef struct binding_t { action_t action; // Change type depending on input handling back-end. like u16 for GLFW_KEY - scancode_t scancode; - scancode_t scancode_alt; + keycode_t keycode; + keycode_t keycode_alt; u64 since_last_activation; } binding_t; typedef struct i_ctx { binding_t* bindings; - isize len; + usize len; } i_ctx; void i_ctx_t_free(i_ctx* c); /* Executes all callbacks that has been pushed onto the callstack and resets the * callstack */ void i_flush_bindings(u64 dt, usize numcalls, input_callback_t* c[], void* state_mem); -action_t i_get_action(const i_ctx* restrict ctx, u64 time, scancode_t scancode); +action_t i_get_action(const i_ctx* restrict ctx, u64 time, keycode_t keycode); void key_callback(void* window, int key, int scancode, int action, int mods); @@ -63,13 +65,13 @@ void i_ctx_push(i_ctx* ctx); void i_ctx_pop(void); void i_ctx_reset(void); -/* Finds and updates the scancode of a binding with the given action in ctx */ -void i_bind_ctx(i_ctx* c, scancode_t s, action_t* a); -void i_bind_ctx_alt(i_ctx* c, scancode_t s, action_t* a); +/* Finds and updates the keycode of a binding with the given action in ctx */ +void i_bind_ctx(i_ctx* c, keycode_t s, action_t* a); +void i_bind_ctx_alt(i_ctx* c, keycode_t s, action_t* a); -/* Update the scancode of a binding */ -void i_bind(binding_t* b, scancode_t s); -void i_bind_alt(binding_t* b, scancode_t s); +/* Update the keycode of a binding */ +void i_bind(binding_t* b, keycode_t s); +void i_bind_alt(binding_t* b, keycode_t s); #define BindAction(key, altkey, f_action) \ (binding_t) { \ @@ -79,7 +81,7 @@ void i_bind_alt(binding_t* b, scancode_t s); .callback = (input_callback_t*)&f_action, \ .callback_str = strdup(#f_action), \ }}, \ - .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \ + .keycode = key, .keycode_alt = altkey, .since_last_activation = 0 \ } #define BindState(key, altkey, f_activate, f_deactivate) \ @@ -93,7 +95,7 @@ void i_bind_alt(binding_t* b, scancode_t s); .activate_str = strdup(#f_activate), \ .deactivate_str = strdup(#f_deactivate), \ }}, \ - .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \ + .keycode = key, .keycode_alt = altkey, .since_last_activation = 0 \ } #ifdef __cplusplus diff --git a/src/ctrl/include/engine/ctrl/keycodes.h b/src/ctrl/include/engine/ctrl/keycodes.h new file mode 100644 index 0000000..4fff38e --- /dev/null +++ b/src/ctrl/include/engine/ctrl/keycodes.h @@ -0,0 +1,93 @@ +#ifndef ENGINE_CTRL_SCANCODES_H + +#ifdef __cplusplus +extern "C" { +#endif + +// We want to reserve the following bytes marked with X for MODS, +// one bit per MODIFIER (shift, control, alt, super): +// XXXX 0000 0000 0000 0000 0000 0000 0000 +// +// We want to reserve the following bytes marked with X for ACTIONS +// enumerate by action type, pressed, released, repeat +// 0000 0000 XXXX 0000 0000 0000 0000 0000 +// +// We want to reserve the following bytes marked with X for the KEYCODE +// 0000 0000 0000 0000 XXXX XXXX XXXX XXXX +#define KEY_MOD(x) 1 << (32-4 + x) +#define ACTION(x) (1 << (32-8)) + x + +typedef enum { + KEY_SPACE = ' ', + KEY_APOSTROPHE = '\'', + KEY_COMMA = ',', + KEY_MINUS = '-', + KEY_PERIOD = '.', + KEY_SLASH = '/', + + KEY_0 = '0', + KEY_1 = '1', + KEY_2 = '2', + KEY_3 = '3', + KEY_4 = '4', + KEY_5 = '5', + KEY_6 = '6', + KEY_7 = '7', + KEY_8 = '8', + KEY_9 = '9', + + KEY_SEMICOLON = ';', + KEY_EQUAL = '=', + + KEY_A = 'A', + KEY_B = 'B', + KEY_C = 'C', + KEY_D = 'D', + KEY_E = 'E', + KEY_F = 'F', + KEY_G = 'G', + KEY_H = 'H', + KEY_I = 'I', + KEY_J = 'J', + KEY_K = 'K', + KEY_L = 'L', + KEY_M = 'M', + KEY_N = 'N', + KEY_O = 'O', + KEY_P = 'P', + KEY_Q = 'Q', + KEY_R = 'R', + KEY_S = 'S', + KEY_T = 'T', + KEY_U = 'U', + KEY_V = 'V', + KEY_W = 'W', + KEY_X = 'X', + KEY_Y = 'Y', + KEY_Z = 'Z', + + KEY_LEFT_BRACKET = '[', + KEY_BACKSLASH = '\\', + KEY_RIGHT_BRACKET = ']', + KEY_GRAVE_ACCENT = '`', + + ACTION_PRESS = ACTION(0), + ACTION_RELEASE = ACTION(1), + ACTION_REPEAT = ACTION(2), + + MOD_SHIFT = KEY_MOD(0), + MOD_CONTROL = KEY_MOD(1), + MOD_ALT = KEY_MOD(2), + MOD_SUPER = KEY_MOD(3), +} KeyCode; +#define MOD_SHFT MOD_SHIFT +#define MOD_CTRL MOD_CONTROL +#define MOD_SUPR MOD_SUPER + +#undef ACTION +#undef KEY_MOD + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/ctrl/include/engine/ctrl/scancodes.h b/src/ctrl/include/engine/ctrl/scancodes.h index f01394e..5b18833 100644 --- a/src/ctrl/include/engine/ctrl/scancodes.h +++ b/src/ctrl/include/engine/ctrl/scancodes.h @@ -18,67 +18,67 @@ extern "C" { #define ACTION(x) (1 << (32-8)) + x typedef enum { - KEY_SPACE = ' ', - KEY_APOSTROPHE = '\'', - KEY_COMMA = ',', - KEY_MINUS = '-', - KEY_PERIOD = '.', - KEY_SLASH = '/', + SCAN_KEY_SPACE = ' ', + SCAN_KEY_APOSTROPHE = '\'', + SCAN_KEY_COMMA = ',', + SCAN_KEY_MINUS = '-', + SCAN_KEY_PERIOD = '.', + SCAN_KEY_SLASH = '/', - KEY_0 = '0', - KEY_1 = '1', - KEY_2 = '2', - KEY_3 = '3', - KEY_4 = '4', - KEY_5 = '5', - KEY_6 = '6', - KEY_7 = '7', - KEY_8 = '8', - KEY_9 = '9', + SCAN_KEY_0 = '0', + SCAN_KEY_1 = '1', + SCAN_KEY_2 = '2', + SCAN_KEY_3 = '3', + SCAN_KEY_4 = '4', + SCAN_KEY_5 = '5', + SCAN_KEY_6 = '6', + SCAN_KEY_7 = '7', + SCAN_KEY_8 = '8', + SCAN_KEY_9 = '9', - KEY_SEMICOLON = ';', - KEY_EQUAL = '=', + SCAN_KEY_SEMICOLON = ';', + SCAN_KEY_EQUAL = '=', - KEY_A = 'A', - KEY_B = 'B', - KEY_C = 'C', - KEY_D = 'D', - KEY_E = 'E', - KEY_F = 'F', - KEY_G = 'G', - KEY_H = 'H', - KEY_I = 'I', - KEY_J = 'J', - KEY_K = 'K', - KEY_L = 'L', - KEY_M = 'M', - KEY_N = 'N', - KEY_O = 'O', - KEY_P = 'P', - KEY_Q = 'Q', - KEY_R = 'R', - KEY_S = 'S', - KEY_T = 'T', - KEY_U = 'U', - KEY_V = 'V', - KEY_W = 'W', - KEY_X = 'X', - KEY_Y = 'Y', - KEY_Z = 'Z', + SCAN_KEY_A = 'A', + SCAN_KEY_B = 'B', + SCAN_KEY_C = 'C', + SCAN_KEY_D = 'D', + SCAN_KEY_E = 'E', + SCAN_KEY_F = 'F', + SCAN_KEY_G = 'G', + SCAN_KEY_H = 'H', + SCAN_KEY_I = 'I', + SCAN_KEY_J = 'J', + SCAN_KEY_K = 'K', + SCAN_KEY_L = 'L', + SCAN_KEY_M = 'M', + SCAN_KEY_N = 'N', + SCAN_KEY_O = 'O', + SCAN_KEY_P = 'P', + SCAN_KEY_Q = 'Q', + SCAN_KEY_R = 'R', + SCAN_KEY_S = 'S', + SCAN_KEY_T = 'T', + SCAN_KEY_U = 'U', + SCAN_KEY_V = 'V', + SCAN_KEY_W = 'W', + SCAN_KEY_X = 'X', + SCAN_KEY_Y = 'Y', + SCAN_KEY_Z = 'Z', - KEY_LEFT_BRACKET = '[', - KEY_BACKSLASH = '\\', - KEY_RIGHT_BRACKET = ']', - KEY_GRAVE_ACCENT = '`', + SCAN_KEY_LEFT_BRACKET = '[', + SCAN_KEY_BACKSLASH = '\\', + SCAN_KEY_RIGHT_BRACKET = ']', + SCAN_KEY_GRAVE_ACCENT = '`', - ACTION_PRESS = ACTION(0), - ACTION_RELEASE = ACTION(1), - ACTION_REPEAT = ACTION(2), + SCAN_ACTION_PRESS = ACTION(0), + SCAN_ACTION_RELEASE = ACTION(1), + SCAN_ACTION_REPEAT = ACTION(2), - MOD_SHIFT = MOD(0), - MOD_CONTROL = MOD(1), - MOD_ALT = MOD(2), - MOD_SUPER = MOD(3), + SCAN_MOD_SHIFT = MOD(0), + SCAN_MOD_CONTROL = MOD(1), + SCAN_MOD_ALT = MOD(2), + SCAN_MOD_SUPER = MOD(3), } ScanCode; #undef ACTION #undef MOD diff --git a/src/ctrl/src/input.c b/src/ctrl/src/input.c index b3db96c..5a08543 100644 --- a/src/ctrl/src/input.c +++ b/src/ctrl/src/input.c @@ -21,7 +21,7 @@ extern Platform* GLOBAL_PLATFORM; .callback = NULL, \ .callback_str = strdup(action_str), \ }}, \ - .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \ + .keycode = key, .keycode_alt = altkey, .since_last_activation = 0 \ } #define BindStateLazy(key, altkey, _activate_str, _deactivate_str) \ @@ -34,7 +34,7 @@ extern Platform* GLOBAL_PLATFORM; .activate_str = strdup(_activate_str), \ .deactivate_str = strdup(_deactivate_str), \ }}, \ - .scancode = key, .scancode_alt = altkey, .since_last_activation = 0 \ + .keycode = key, .keycode_alt = altkey, .since_last_activation = 0 \ } void key_callback(void* window, int key, int scancode, int action, int mods) { @@ -45,7 +45,7 @@ void key_callback(void* window, int key, int scancode, int action, int mods) { const u64 now = get_time(); for (usize b = 0; b < bindings_len; b++) { - const action_t a = i_get_action(&bindings[b], now, scancode); + const action_t a = i_get_action(&bindings[b], now, key); switch (action) { case GLFW_PRESS: @@ -62,10 +62,14 @@ void key_callback(void* window, int key, int scancode, int action, int mods) { } break; case InputType_range: +#ifdef _DEBUG WARN("Range inputs not supported yet!"); +#endif break; case InputType_error: - WARN("Unhandled scancode: %lu", scancode); +#ifdef _DEBUG + WARN("Unhandled keycode: %lu", key); +#endif default: break; @@ -117,7 +121,7 @@ void binding_t_free(binding_t* b) { } void i_ctx_t_free(i_ctx* c) { - for (isize i = 0; i < c->len; i++) { + for (usize i = 0; i < c->len; i++) { binding_t_free(&c->bindings[i]); } } @@ -143,17 +147,17 @@ bool binding_action_cmp(binding_t* restrict a, binding_t* restrict b) { return false; } -bool binding_scancode_cmp(binding_t* restrict a, binding_t* restrict b) { - return a->scancode == b->scancode || a->scancode_alt == b->scancode_alt; +bool binding_keycode_cmp(binding_t* restrict a, binding_t* restrict b) { + return a->keycode == b->keycode || a->keycode_alt == b->keycode_alt; } -bool binding_scancode_cmp_i(binding_t* restrict a, scancode_t scancode) { - return a->scancode == scancode || a->scancode_alt == scancode; +bool binding_keycode_cmp_i(binding_t* restrict a, keycode_t keycode) { + return a->keycode == keycode || a->keycode_alt == keycode; } // If any binding in ctx contains action, replace that entry. bool i_update_binding(i_ctx* ctx, binding_t* binding) { - isize idx = 0; + usize idx = 0; if (ctx == NULL || binding == NULL) { ERROR("i_update_binding received nullptr!"); return false; @@ -163,26 +167,26 @@ bool i_update_binding(i_ctx* ctx, binding_t* binding) { idx++; if (idx < ctx->len && binding_action_cmp(&ctx->bindings[idx], binding)) { - ctx->bindings[idx].scancode = binding->scancode; - ctx->bindings[idx].scancode_alt = binding->scancode_alt; + ctx->bindings[idx].keycode = binding->keycode; + ctx->bindings[idx].keycode_alt = binding->keycode_alt; return true; } return false; } -// If any binding in ctx contains scancode, replace that action. +// If any binding in ctx contains keycode, replace that action. bool i_update_unique_binding(i_ctx* ctx, binding_t* binding) { - isize idx = 0; + usize idx = 0; if (ctx == NULL || binding == NULL) { ERROR("i_update_unique_binding received nullptr!"); return false; } - while (idx < ctx->len && !binding_scancode_cmp(&ctx->bindings[idx], binding)) + while (idx < ctx->len && !binding_keycode_cmp(&ctx->bindings[idx], binding)) idx++; - if (idx < ctx->len && binding_scancode_cmp(&ctx->bindings[idx], binding)) { + if (idx < ctx->len && binding_keycode_cmp(&ctx->bindings[idx], binding)) { ctx->bindings[idx].action = binding->action; return true; } @@ -201,19 +205,44 @@ void i_flush_bindings(u64 dt, usize numcalls, input_callback_t* c[], void* state } action_t i_get_action(const i_ctx* restrict ctx, u64 time, - scancode_t scancode) { - isize idx = 0; + keycode_t keycode) { + usize idx = 0; if (ctx == NULL) { ERROR("%s received nullptr!", __func__); return (action_t){.type = InputType_error}; } + // Needed for glfw + switch (keycode) { + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + keycode = MOD_SHIFT; + break; + + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + keycode = MOD_CONTROL; + break; + + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + keycode = MOD_ALT; + break; + + case GLFW_KEY_LEFT_SUPER: + case GLFW_KEY_RIGHT_SUPER: + keycode = MOD_SUPER; + break; + + default: break; + } + while (idx < ctx->len && - !binding_scancode_cmp_i(&ctx->bindings[idx], scancode)) + !binding_keycode_cmp_i(&ctx->bindings[idx], keycode)) idx++; - if (idx < ctx->len && binding_scancode_cmp_i(&ctx->bindings[idx], scancode)) { + if (idx < ctx->len && binding_keycode_cmp_i(&ctx->bindings[idx], keycode)) { ctx->bindings[idx].since_last_activation = time; return ctx->bindings[idx].action; } @@ -238,16 +267,16 @@ i_ctx* i_ctx_dup(i_ctx** ctx, usize ctx_len) { ret[c].len = ctx[c]->len; ret[c].bindings = &bb[cumsum]; - for (isize i = 0; i < ctx[c]->len; i++) { + for (usize 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, + bb[cumsum] = BindActionLazy(b[i].keycode, b[i].keycode_alt, strdup(b[i].action.action.callback_str)); break; case InputType_state: - bb[cumsum] = BindStateLazy(b[i].scancode, b[i].scancode_alt, + bb[cumsum] = BindStateLazy(b[i].keycode, b[i].keycode_alt, strdup(b[i].action.state.activate_str), strdup(b[i].action.state.deactivate_str)); break; @@ -264,7 +293,7 @@ i_ctx* i_ctx_dup(i_ctx** ctx, usize ctx_len) { /* 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++) { + for (usize i = 0; i < c->len; i++) { if (c->bindings[i].action.type != a->type) continue; switch (c->bindings[i].action.type) { @@ -295,7 +324,7 @@ binding_t* get_action(i_ctx* c, action_t* a) { return NULL; } -void i_bind_ctx(i_ctx* c, scancode_t s, action_t* a) { +void i_bind_ctx(i_ctx* c, keycode_t s, action_t* a) { binding_t* b = get_action(c, a); if (b == NULL) { @@ -303,10 +332,10 @@ void i_bind_ctx(i_ctx* c, scancode_t s, action_t* a) { return; } - b->scancode = s; + b->keycode = s; } -void i_bind_ctx_alt(i_ctx* c, scancode_t s, action_t* a) { +void i_bind_ctx_alt(i_ctx* c, keycode_t s, action_t* a) { binding_t* b = get_action(c, a); if (b == NULL) { @@ -314,25 +343,25 @@ void i_bind_ctx_alt(i_ctx* c, scancode_t s, action_t* a) { return; } - b->scancode_alt = s; + b->keycode_alt = s; } -void i_bind(binding_t* b, scancode_t s) { +void i_bind(binding_t* b, keycode_t s) { if (b == NULL) { WARN("Failed to update keybinding"); return; } - b->scancode = s; + b->keycode = s; } -void i_bind_alt(binding_t* b, scancode_t s) { +void i_bind_alt(binding_t* b, keycode_t s) { if (b == NULL) { WARN("Failed to update keybinding"); return; } - b->scancode_alt = s; + b->keycode_alt = s; } /* Pushes an input context onto the input handling stack */ @@ -353,7 +382,7 @@ void i_ctx_push(i_ctx* ctx) { } LOG("Bindings in ctx[%d]:", GLOBAL_PLATFORM->bindings_len); - for (isize i = 0; i < ctx->len; i++) { + for (usize i = 0; i < ctx->len; i++) { switch (ctx->bindings[i].action.type) { case InputType_error: LOG("(error)"); -- cgit v1.3