diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba57b6f..da04812 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ set(components gfx gui header + input instance keyboard menu diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt new file mode 100644 index 0000000..9de4843 --- /dev/null +++ b/src/input/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(input + "src/input.c" +) +target_include_directories(input PUBLIC "inc") +target_link_libraries(input PUBLIC keyboard mouse pad peripheral) diff --git a/src/input/inc/input.h b/src/input/inc/input.h new file mode 100644 index 0000000..2dd401b --- /dev/null +++ b/src/input/inc/input.h @@ -0,0 +1,56 @@ +#ifndef INPUT_H +#define INPUT_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void (*input_ch)(char ch, void *user); +typedef void (*input_erase)(void *user); + +struct input +{ + input_ch cb; + input_erase erase; + void *user; + unsigned char t; + bool repeat; + struct keyboard_combo prev; +}; + +void input_update(struct input *in, const union peripheral *p); +int input_render(const struct input *in, const union peripheral *p); +bool input_keyboard_justpressed(const struct input *in, + const struct keyboard *k, + const struct keyboard_combo *c); +bool input_keyboard_pressed(const struct input *in, + const struct keyboard *k, + const struct keyboard_combo *c); +bool input_keyboard_justreleased(const struct input *in, + const struct keyboard *k, + const struct keyboard_combo *c); +bool input_pad_pressed(const struct input *in, const struct pad *p, + enum pad_key k); +bool input_pad_justpressed(const struct input *in, const struct pad *p, + enum pad_key k); +bool input_pad_released(const struct input *in, const struct pad *p, + enum pad_key k); +bool input_mouse_pressed(const struct input *in, const struct mouse *m, + enum mouse_button b); +bool input_mouse_justpressed(const struct input *in, const struct mouse *m, + enum mouse_button b); +bool input_mouse_justreleased(const struct input *in, const struct mouse *m, + enum mouse_button b); + +#ifdef __cplusplus +} +#endif + +#endif /* INPUT_H */ diff --git a/src/input/src/input.c b/src/input/src/input.c new file mode 100644 index 0000000..bb94424 --- /dev/null +++ b/src/input/src/input.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void send_input(struct input *const in, const struct keyboard *const k, + const enum keyboard_key key) +{ + if (key != KEYBOARD_KEY_NONE) + { + switch (key) + { + case KEYBOARD_KEY_BACKSPACE: + in->erase(in->user); + break; + + case KEYBOARD_KEY_ESC: + *in = (const struct input){0}; + break; + + default: + { + const char ch = keyboard_to_char(k, key); + + if (isprint(ch)) + in->cb(ch, in->user); + } + break; + } + } +} + +static void update_keyboard(struct input *const in, + const struct keyboard *const k) +{ + struct keyboard_combo c; + + if (keyboard_any_justpressed(k, &c)) + for (size_t i = 0; i < sizeof c.keys / sizeof *c.keys; i++) + send_input(in, k, c.keys[i]); + else if (keyboard_any_pressed(k, &c)) + { + if (memcmp(&c, &in->prev, sizeof c)) + { + in->repeat = false; + in->t = 0; + } + else + { + enum {LONG_INTERVAL = 25, SHORT_INTERVAL = 2}; + + if (!in->repeat) + { + if (++in->t >= LONG_INTERVAL) + in->repeat = true; + } + else if (++in->t >= SHORT_INTERVAL) + { + for (size_t i = 0; + i < sizeof c.keys / sizeof *c.keys; i++) + send_input(in, k, c.keys[i]); + + in->t = 0; + } + } + + in->prev = c; + } + else + { + in->repeat = false; + in->t = 0; + } +} + +void input_update(struct input *const in, const union peripheral *const p) +{ + switch (p->common.type) + { + case PERIPHERAL_TYPE_KEYBOARD_MOUSE: + if (in->cb && in->erase) + update_keyboard(in, &p->kbm.keyboard); + + break; + + case PERIPHERAL_TYPE_TOUCH: + /* Fall through. */ + case PERIPHERAL_TYPE_PAD: + break; + } +} + +int input_render(const struct input *const in, const union peripheral *const p) +{ + switch (p->common.type) + { + case PERIPHERAL_TYPE_KEYBOARD_MOUSE: + return 0; + + case PERIPHERAL_TYPE_TOUCH: + /* Fall through. */ + case PERIPHERAL_TYPE_PAD: + break; + } + + return -1; +} + +bool input_keyboard_justpressed(const struct input *const in, + const struct keyboard *const k, + const struct keyboard_combo *const c) +{ + return in->cb ? false : keyboard_justpressed(k, c); +} + +bool input_keyboard_pressed(const struct input *const in, + const struct keyboard *const k, + const struct keyboard_combo *const c) +{ + return in->cb ? false : keyboard_pressed(k, c); +} + +bool input_keyboard_justreleased(const struct input *const in, + const struct keyboard *const k, + const struct keyboard_combo *const c) +{ + return in->cb ? false : keyboard_justreleased(k, c); +} + +bool input_pad_pressed(const struct input *const in, + const struct pad *const p, + const enum pad_key k) +{ + return in->cb ? false : pad_pressed(p, k); +} + +bool input_pad_justpressed(const struct input *const in, + const struct pad *const p, + const enum pad_key k) +{ + return in->cb ? false : pad_justpressed(p, k); +} + +bool input_pad_released(const struct input *const in, + const struct pad *const p, + const enum pad_key k) +{ + return in->cb ? false : pad_released(p, k); +} + +bool input_mouse_pressed(const struct input *const in, + const struct mouse *const m, + const enum mouse_button b) +{ + return in->cb ? false : mouse_pressed(m, b); +} + +bool input_mouse_justpressed(const struct input *const in, + const struct mouse *const m, + const enum mouse_button b) +{ + return in->cb ? false : mouse_justpressed(m, b); +} + +bool input_mouse_justreleased(const struct input *const in, + const struct mouse *const m, + const enum mouse_button b) +{ + return in->cb ? false : mouse_justreleased(m, b); +}