diff --git a/app/meson.build b/app/meson.build index 720d9c8c..7d9c2b5c 100644 --- a/app/meson.build +++ b/app/meson.build @@ -28,6 +28,7 @@ src = [ 'src/video_buffer.c', 'src/util/acksync.c', 'src/util/file.c', + 'src/util/intmap.c', 'src/util/intr.c', 'src/util/log.c', 'src/util/net.c', diff --git a/app/src/keyboard_inject.c b/app/src/keyboard_inject.c index 83924ab7..bb3bb953 100644 --- a/app/src/keyboard_inject.c +++ b/app/src/keyboard_inject.c @@ -6,60 +6,115 @@ #include "android/input.h" #include "control_msg.h" #include "controller.h" +#include "util/intmap.h" #include "util/log.h" /** Downcast key processor to sc_keyboard_inject */ #define DOWNCAST(KP) container_of(KP, struct sc_keyboard_inject, key_processor) -#define MAP(FROM, TO) case FROM: *to = TO; return true -#define FAIL default: return false static bool convert_keycode_action(SDL_EventType from, enum android_keyevent_action *to) { - switch (from) { - MAP(SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN); - MAP(SDL_KEYUP, AKEY_EVENT_ACTION_UP); - FAIL; + static const struct sc_intmap_entry actions[] = { + {SDL_KEYDOWN, AKEY_EVENT_ACTION_DOWN}, + {SDL_KEYUP, AKEY_EVENT_ACTION_UP}, + }; + + const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from); + if (entry) { + *to = entry->value; + return true; } + + return false; } static bool convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod, bool prefer_text) { - switch (from) { - MAP(SDLK_RETURN, AKEYCODE_ENTER); - MAP(SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER); - MAP(SDLK_ESCAPE, AKEYCODE_ESCAPE); - MAP(SDLK_BACKSPACE, AKEYCODE_DEL); - MAP(SDLK_TAB, AKEYCODE_TAB); - MAP(SDLK_PAGEUP, AKEYCODE_PAGE_UP); - MAP(SDLK_DELETE, AKEYCODE_FORWARD_DEL); - MAP(SDLK_HOME, AKEYCODE_MOVE_HOME); - MAP(SDLK_END, AKEYCODE_MOVE_END); - MAP(SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN); - MAP(SDLK_RIGHT, AKEYCODE_DPAD_RIGHT); - MAP(SDLK_LEFT, AKEYCODE_DPAD_LEFT); - MAP(SDLK_DOWN, AKEYCODE_DPAD_DOWN); - MAP(SDLK_UP, AKEYCODE_DPAD_UP); - MAP(SDLK_LCTRL, AKEYCODE_CTRL_LEFT); - MAP(SDLK_RCTRL, AKEYCODE_CTRL_RIGHT); - MAP(SDLK_LSHIFT, AKEYCODE_SHIFT_LEFT); - MAP(SDLK_RSHIFT, AKEYCODE_SHIFT_RIGHT); + // Navigation keys and ENTER. + // Used in all modes. + static const struct sc_intmap_entry special_keys[] = { + {SDLK_RETURN, AKEYCODE_ENTER}, + {SDLK_KP_ENTER, AKEYCODE_NUMPAD_ENTER}, + {SDLK_ESCAPE, AKEYCODE_ESCAPE}, + {SDLK_BACKSPACE, AKEYCODE_DEL}, + {SDLK_TAB, AKEYCODE_TAB}, + {SDLK_PAGEUP, AKEYCODE_PAGE_UP}, + {SDLK_DELETE, AKEYCODE_FORWARD_DEL}, + {SDLK_HOME, AKEYCODE_MOVE_HOME}, + {SDLK_END, AKEYCODE_MOVE_END}, + {SDLK_PAGEDOWN, AKEYCODE_PAGE_DOWN}, + {SDLK_RIGHT, AKEYCODE_DPAD_RIGHT}, + {SDLK_LEFT, AKEYCODE_DPAD_LEFT}, + {SDLK_DOWN, AKEYCODE_DPAD_DOWN}, + {SDLK_UP, AKEYCODE_DPAD_UP}, + {SDLK_LCTRL, AKEYCODE_CTRL_LEFT}, + {SDLK_RCTRL, AKEYCODE_CTRL_RIGHT}, + {SDLK_LSHIFT, AKEYCODE_SHIFT_LEFT}, + {SDLK_RSHIFT, AKEYCODE_SHIFT_RIGHT}, + }; + + // Numpad navigation keys. + // Used in all modes, when NumLock and Shift are disabled. + static const struct sc_intmap_entry kp_nav_keys[] = { + {SDLK_KP_0, AKEYCODE_INSERT}, + {SDLK_KP_1, AKEYCODE_MOVE_END}, + {SDLK_KP_2, AKEYCODE_DPAD_DOWN}, + {SDLK_KP_3, AKEYCODE_PAGE_DOWN}, + {SDLK_KP_4, AKEYCODE_DPAD_LEFT}, + {SDLK_KP_6, AKEYCODE_DPAD_RIGHT}, + {SDLK_KP_7, AKEYCODE_MOVE_HOME}, + {SDLK_KP_8, AKEYCODE_DPAD_UP}, + {SDLK_KP_9, AKEYCODE_PAGE_UP}, + {SDLK_KP_PERIOD, AKEYCODE_FORWARD_DEL}, + }; + + // Letters and space. + // Used in non-text mode. + static const struct sc_intmap_entry alphaspace_keys[] = { + {SDLK_a, AKEYCODE_A}, + {SDLK_b, AKEYCODE_B}, + {SDLK_c, AKEYCODE_C}, + {SDLK_d, AKEYCODE_D}, + {SDLK_e, AKEYCODE_E}, + {SDLK_f, AKEYCODE_F}, + {SDLK_g, AKEYCODE_G}, + {SDLK_h, AKEYCODE_H}, + {SDLK_i, AKEYCODE_I}, + {SDLK_j, AKEYCODE_J}, + {SDLK_k, AKEYCODE_K}, + {SDLK_l, AKEYCODE_L}, + {SDLK_m, AKEYCODE_M}, + {SDLK_n, AKEYCODE_N}, + {SDLK_o, AKEYCODE_O}, + {SDLK_p, AKEYCODE_P}, + {SDLK_q, AKEYCODE_Q}, + {SDLK_r, AKEYCODE_R}, + {SDLK_s, AKEYCODE_S}, + {SDLK_t, AKEYCODE_T}, + {SDLK_u, AKEYCODE_U}, + {SDLK_v, AKEYCODE_V}, + {SDLK_w, AKEYCODE_W}, + {SDLK_x, AKEYCODE_X}, + {SDLK_y, AKEYCODE_Y}, + {SDLK_z, AKEYCODE_Z}, + {SDLK_SPACE, AKEYCODE_SPACE}, + }; + + const struct sc_intmap_entry *entry = + SC_INTMAP_FIND_ENTRY(special_keys, from); + if (entry) { + *to = entry->value; + return true; } if (!(mod & (KMOD_NUM | KMOD_SHIFT))) { // Handle Numpad events when Num Lock is disabled // If SHIFT is pressed, a text event will be sent instead - switch(from) { - MAP(SDLK_KP_0, AKEYCODE_INSERT); - MAP(SDLK_KP_1, AKEYCODE_MOVE_END); - MAP(SDLK_KP_2, AKEYCODE_DPAD_DOWN); - MAP(SDLK_KP_3, AKEYCODE_PAGE_DOWN); - MAP(SDLK_KP_4, AKEYCODE_DPAD_LEFT); - MAP(SDLK_KP_6, AKEYCODE_DPAD_RIGHT); - MAP(SDLK_KP_7, AKEYCODE_MOVE_HOME); - MAP(SDLK_KP_8, AKEYCODE_DPAD_UP); - MAP(SDLK_KP_9, AKEYCODE_PAGE_UP); - MAP(SDLK_KP_PERIOD, AKEYCODE_FORWARD_DEL); + entry = SC_INTMAP_FIND_ENTRY(kp_nav_keys, from); + if (entry) { + *to = entry->value; + return true; } } @@ -71,37 +126,15 @@ convert_keycode(SDL_Keycode from, enum android_keycode *to, uint16_t mod, if (mod & (KMOD_LALT | KMOD_RALT | KMOD_LGUI | KMOD_RGUI)) { return false; } + // if ALT and META are not pressed, also handle letters and space - switch (from) { - MAP(SDLK_a, AKEYCODE_A); - MAP(SDLK_b, AKEYCODE_B); - MAP(SDLK_c, AKEYCODE_C); - MAP(SDLK_d, AKEYCODE_D); - MAP(SDLK_e, AKEYCODE_E); - MAP(SDLK_f, AKEYCODE_F); - MAP(SDLK_g, AKEYCODE_G); - MAP(SDLK_h, AKEYCODE_H); - MAP(SDLK_i, AKEYCODE_I); - MAP(SDLK_j, AKEYCODE_J); - MAP(SDLK_k, AKEYCODE_K); - MAP(SDLK_l, AKEYCODE_L); - MAP(SDLK_m, AKEYCODE_M); - MAP(SDLK_n, AKEYCODE_N); - MAP(SDLK_o, AKEYCODE_O); - MAP(SDLK_p, AKEYCODE_P); - MAP(SDLK_q, AKEYCODE_Q); - MAP(SDLK_r, AKEYCODE_R); - MAP(SDLK_s, AKEYCODE_S); - MAP(SDLK_t, AKEYCODE_T); - MAP(SDLK_u, AKEYCODE_U); - MAP(SDLK_v, AKEYCODE_V); - MAP(SDLK_w, AKEYCODE_W); - MAP(SDLK_x, AKEYCODE_X); - MAP(SDLK_y, AKEYCODE_Y); - MAP(SDLK_z, AKEYCODE_Z); - MAP(SDLK_SPACE, AKEYCODE_SPACE); - FAIL; + entry = SC_INTMAP_FIND_ENTRY(alphaspace_keys, from); + if (entry) { + *to = entry->value; + return true; } + + return false; } static enum android_metastate diff --git a/app/src/mouse_inject.c b/app/src/mouse_inject.c index 1d5fe230..8f7e363d 100644 --- a/app/src/mouse_inject.c +++ b/app/src/mouse_inject.c @@ -6,6 +6,7 @@ #include "android/input.h" #include "control_msg.h" #include "controller.h" +#include "util/intmap.h" #include "util/log.h" /** Downcast mouse processor to sc_mouse_inject */ @@ -32,25 +33,37 @@ convert_mouse_buttons(uint32_t state) { return buttons; } -#define MAP(FROM, TO) case FROM: *to = TO; return true -#define FAIL default: return false static bool convert_mouse_action(SDL_EventType from, enum android_motionevent_action *to) { - switch (from) { - MAP(SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN); - MAP(SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP); - FAIL; + static const struct sc_intmap_entry actions[] = { + {SDL_MOUSEBUTTONDOWN, AMOTION_EVENT_ACTION_DOWN}, + {SDL_MOUSEBUTTONUP, AMOTION_EVENT_ACTION_UP}, + }; + + const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from); + if (entry) { + *to = entry->value; + return true; } + + return false; } static bool convert_touch_action(SDL_EventType from, enum android_motionevent_action *to) { - switch (from) { - MAP(SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE); - MAP(SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN); - MAP(SDL_FINGERUP, AMOTION_EVENT_ACTION_UP); - FAIL; + static const struct sc_intmap_entry actions[] = { + {SDL_FINGERMOTION, AMOTION_EVENT_ACTION_MOVE}, + {SDL_FINGERDOWN, AMOTION_EVENT_ACTION_DOWN}, + {SDL_FINGERUP, AMOTION_EVENT_ACTION_UP}, + }; + + const struct sc_intmap_entry *entry = SC_INTMAP_FIND_ENTRY(actions, from); + if (entry) { + *to = entry->value; + return true; } + + return false; } static bool diff --git a/app/src/util/intmap.c b/app/src/util/intmap.c new file mode 100644 index 00000000..fa11acef --- /dev/null +++ b/app/src/util/intmap.c @@ -0,0 +1,13 @@ +#include "intmap.h" + +const struct sc_intmap_entry * +sc_intmap_find_entry(const struct sc_intmap_entry entries[], size_t len, + int32_t key) { + for (size_t i = 0; i < len; ++i) { + const struct sc_intmap_entry *entry = &entries[i]; + if (entry->key == key) { + return entry; + } + } + return NULL; +} diff --git a/app/src/util/intmap.h b/app/src/util/intmap.h new file mode 100644 index 00000000..2898c461 --- /dev/null +++ b/app/src/util/intmap.h @@ -0,0 +1,24 @@ +#ifndef SC_ARRAYMAP_H +#define SC_ARRAYMAP_H + +#include "common.h" + +#include + +struct sc_intmap_entry { + int32_t key; + int32_t value; +}; + +const struct sc_intmap_entry * +sc_intmap_find_entry(const struct sc_intmap_entry entries[], size_t len, + int32_t key); + +/** + * MAP is expected to be a static array of sc_intmap_entry, so that + * ARRAY_LEN(MAP) can be computed statically. + */ +#define SC_INTMAP_FIND_ENTRY(MAP, KEY) \ + sc_intmap_find_entry(MAP, ARRAY_LEN(MAP), KEY) + +#endif