aboutsummaryrefslogtreecommitdiff
path: root/patches/libpicofe
diff options
context:
space:
mode:
authorneonloop2021-08-12 15:29:39 +0000
committerneonloop2021-08-12 15:29:39 +0000
commit4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51 (patch)
tree88bf75a3ffac4017fe5124f935fe5e5f67dd6e48 /patches/libpicofe
parentc17d20ab28e0ac7dd527ff840559d96e98931a80 (diff)
downloadpicoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.gz
picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.bz2
picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.zip
Adds combo key support to libpicofe
Diffstat (limited to 'patches/libpicofe')
-rw-r--r--patches/libpicofe/0001-key-combos.patch157
1 files changed, 157 insertions, 0 deletions
diff --git a/patches/libpicofe/0001-key-combos.patch b/patches/libpicofe/0001-key-combos.patch
new file mode 100644
index 0000000..69cb4be
--- /dev/null
+++ b/patches/libpicofe/0001-key-combos.patch
@@ -0,0 +1,157 @@
+diff --git a/in_sdl.c b/in_sdl.c
+index a84c781..518e8cf 100644
+--- a/in_sdl.c
++++ b/in_sdl.c
+@@ -19,11 +19,18 @@
+ typedef unsigned long keybits_t;
+ #define KEYBITS_WORD_BITS (sizeof(keybits_t) * 8)
+
++enum mod_state {
++ MOD_NO,
++ MOD_MAYBE,
++ MOD_YES
++};
++
+ struct in_sdl_state {
+ const in_drv_t *drv;
+ SDL_Joystick *joy;
+ int joy_id;
+ int axis_keydown[2];
++ enum mod_state mod_state;
+ keybits_t keystate[SDLK_LAST / KEYBITS_WORD_BITS + 1];
+ // emulator keys should always be processed immediately lest one is lost
+ keybits_t emu_keys[SDLK_LAST / KEYBITS_WORD_BITS + 1];
+@@ -259,6 +266,97 @@ static int get_keystate(keybits_t *keystate, int sym)
+ return !!(*ks_word & mask);
+ }
+
++static int translate_keystate(struct in_sdl_state *state, SDL_Event *event)
++{
++ const struct in_pdata *pdata = state->drv->pdata;
++ const struct mod_keymap *map;
++ SDL_Event new_event;
++ short key = (short)event->key.keysym.sym;
++ uint8_t type = event->type;
++ short mod_key = pdata->mod_key;
++ int i;
++ int ret = 1;
++
++ if (!mod_key)
++ return 1;
++
++ if (state->mod_state == MOD_NO && key != mod_key)
++ return 1;
++
++ if (key == mod_key) {
++ if (type == SDL_KEYDOWN) {
++ /* Pressed mod, maybe a combo? Ignore the keypress
++ * until it's determined */
++ state->mod_state = MOD_MAYBE;
++
++ for (i = 0; i < pdata->modmap_size; i++) {
++ map = &pdata->mod_keymap[i];
++
++ if (get_keystate(state->keystate, map->inkey)) {
++ state->mod_state = MOD_YES;
++ new_event.type = SDL_KEYUP;
++ new_event.key.state = SDL_RELEASED;
++ new_event.key.keysym.sym = map->inkey;
++ SDL_PushEvent(&new_event);
++
++ new_event.type = SDL_KEYDOWN;
++ new_event.key.state = SDL_PRESSED;
++ new_event.key.keysym.sym = map->outkey;
++ SDL_PushEvent(&new_event);
++ }
++ }
++
++ ret = -1;
++ } else if (state->mod_state == MOD_MAYBE) {
++ /* Released mod without combo, simulate down and up */
++ SDL_PushEvent(event);
++ state->mod_state = MOD_NO;
++ event->type = SDL_KEYDOWN;
++ ret = 1;
++ } else if (state->mod_state == MOD_YES) {
++ /* Released mod, switch all mod keys to unmod */
++ state->mod_state = MOD_NO;
++
++ for (i = 0; i < pdata->modmap_size; i++) {
++ map = &pdata->mod_keymap[i];
++
++ if (get_keystate(state->keystate, map->outkey)) {
++ state->mod_state = MOD_NO;
++ new_event.type = SDL_KEYUP;
++ new_event.key.state = SDL_RELEASED;
++ new_event.key.keysym.sym = map->outkey;
++ SDL_PushEvent(&new_event);
++
++ new_event.type = SDL_KEYDOWN;
++ new_event.key.state = SDL_PRESSED;
++ new_event.key.keysym.sym = map->inkey;
++ SDL_PushEvent(&new_event);
++ }
++ }
++ ret = -1;
++ }
++ } else {
++ for (i = 0; i < pdata->modmap_size; i++) {
++ map = &pdata->mod_keymap[i];
++
++ if (map->inkey == key) {
++ state->mod_state = MOD_YES;
++
++ /* Releasing the original key? Allow it through,
++ * Otherwise, replace with modified key. */
++ if (!(event->type == SDL_KEYUP &&
++ get_keystate(state->keystate, map->inkey)))
++ event->key.keysym.sym = map->outkey;
++
++ break;
++ }
++ }
++ ret = 1;
++ }
++
++ return ret;
++}
++
+ static int handle_event(struct in_sdl_state *state, SDL_Event *event,
+ int *kc_out, int *down_out, int *emu_out)
+ {
+@@ -267,6 +365,9 @@ static int handle_event(struct in_sdl_state *state, SDL_Event *event,
+ if (event->type != SDL_KEYDOWN && event->type != SDL_KEYUP)
+ return -1;
+
++ if (translate_keystate(state, event) < 0)
++ return -1;
++
+ emu = get_keystate(state->emu_keys, event->key.keysym.sym);
+ update_keystate(state->keystate, event->key.keysym.sym,
+ event->type == SDL_KEYDOWN);
+diff --git a/input.h b/input.h
+index 360b65b..895ad61 100644
+--- a/input.h
++++ b/input.h
+@@ -110,6 +110,11 @@ struct menu_keymap {
+ short pbtn;
+ };
+
++struct mod_keymap {
++ short inkey;
++ short outkey;
++};
++
+ struct in_pdata {
+ const struct in_default_bind *defbinds;
+ const struct menu_keymap *key_map;
+@@ -117,6 +122,9 @@ struct in_pdata {
+ const struct menu_keymap *joy_map;
+ size_t jmap_size;
+ const char * const *key_names;
++ short mod_key;
++ const struct mod_keymap *mod_keymap;
++ size_t modmap_size;
+ };
+
+ /* to be called by drivers */