aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--patches/libpicofe/0001-key-combos.patch186
1 files changed, 114 insertions, 72 deletions
diff --git a/patches/libpicofe/0001-key-combos.patch b/patches/libpicofe/0001-key-combos.patch
index 69cb4be..7105fc3 100644
--- a/patches/libpicofe/0001-key-combos.patch
+++ b/patches/libpicofe/0001-key-combos.patch
@@ -1,5 +1,5 @@
diff --git a/in_sdl.c b/in_sdl.c
-index a84c781..518e8cf 100644
+index a84c781..bab649a 100644
--- a/in_sdl.c
+++ b/in_sdl.c
@@ -19,11 +19,18 @@
@@ -21,78 +21,102 @@ index a84c781..518e8cf 100644
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)
+@@ -259,6 +266,139 @@ 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)
++static inline void switch_key(SDL_Event *event, keybits_t *keystate, short upkey, short downkey)
++{
++ event->type = SDL_KEYUP;
++ event->key.state = SDL_RELEASED;
++ event->key.keysym.sym = upkey;
++
++ update_keystate(keystate, upkey, 0);
++ SDL_PushEvent(event);
++
++ event->type = SDL_KEYDOWN;
++ event->key.state = SDL_PRESSED;
++ event->key.keysym.sym = downkey;
++
++ update_keystate(keystate, downkey, 1);
++ SDL_PushEvent(event);
++}
++
++static void translate_combo_event(struct in_sdl_state *state, SDL_Event *event, keybits_t *keystate)
+{
+ 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 (event->type != SDL_KEYDOWN && event->type != SDL_KEYUP) {
++ SDL_PushEvent(event);
++ return;
++ }
+
-+ if (state->mod_state == MOD_NO && key != mod_key)
-+ return 1;
++ if (state->mod_state == MOD_NO && key != mod_key) {
++ update_keystate(keystate, event->key.keysym.sym, event->type == SDL_KEYDOWN);
++ SDL_PushEvent(event);
++ return;
++ }
+
+ 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);
++ switch (state->mod_state) {
++ case MOD_NO:
++ 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(keystate, map->inkey)) {
++ state->mod_state = MOD_YES;
++ switch_key(event, keystate, map->inkey, map->outkey);
++ }
+ }
++ } else {
++ SDL_PushEvent(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);
++ break;
++ case MOD_MAYBE:
++ if (type == SDL_KEYDOWN) {
++ SDL_PushEvent(event);
++ } else {
++ /* Released mod without combo, simulate down and up */
++ state->mod_state = MOD_NO;
++
++ event->type = SDL_KEYDOWN;
++ event->key.state = SDL_PRESSED;
++ SDL_PushEvent(event);
++
++ event->type = SDL_KEYUP;
++ event->key.state = SDL_RELEASED;
++ SDL_PushEvent(event);
++ }
++ break;
++ case MOD_YES:
++ if (type == SDL_KEYDOWN) {
++ SDL_PushEvent(event);
++ } else {
++ /* Released mod, switch all mod keys to unmod and ignore mod press */
++ state->mod_state = MOD_NO;
++
++ for (i = 0; i < pdata->modmap_size; i++) {
++ map = &pdata->mod_keymap[i];
++
++ if (get_keystate(keystate, map->outkey)) {
++ switch_key(event, keystate, map->outkey, map->inkey);
++ }
+ }
+ }
-+ ret = -1;
++ break;
++ default:
++ SDL_PushEvent(event);
++ break;
+ }
+ } else {
+ for (i = 0; i < pdata->modmap_size; i++) {
@@ -101,34 +125,52 @@ index a84c781..518e8cf 100644
+ 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;
++ event->key.keysym.sym = map->outkey;
++ update_keystate(keystate, map->outkey, event->type == SDL_KEYDOWN);
++ SDL_PushEvent(event);
+ }
+ }
-+ ret = 1;
+ }
++}
++
++static void translate_combo_events(struct in_sdl_state *state, Uint32 mask)
++{
++ const struct in_pdata *pdata = state->drv->pdata;
++ SDL_Event events[10]; /* Must be bigger than events size in collect_events */
++ keybits_t keystate[SDLK_LAST / KEYBITS_WORD_BITS + 1];
++ int count;
++ int has_events;
++ int i;
++
++ if (!pdata->mod_key)
++ return;
+
-+ return ret;
++ has_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask);
++
++ if (!has_events)
++ return;
++
++ memcpy(keystate, state->keystate, sizeof(keystate));
++
++ count = SDL_PeepEvents(events, (sizeof(events) / sizeof(events[0])), SDL_GETEVENT, mask);
++ for (i = 0; i < count; i++) {
++ translate_combo_event(state, &events[i], keystate);
++ }
+}
+
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;
+@@ -363,6 +503,9 @@ static int collect_events(struct in_sdl_state *state, int *one_kc, int *one_down
+
+ SDL_PumpEvents();
-+ if (translate_keystate(state, event) < 0)
-+ return -1;
++ if (!state->joy)
++ translate_combo_events(state, mask);
+
- emu = get_keystate(state->emu_keys, event->key.keysym.sym);
- update_keystate(state->keystate, event->key.keysym.sym,
- event->type == SDL_KEYDOWN);
+ num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask);
+
+ for (num_peeped_events = 0; num_peeped_events < num_events; num_peeped_events += count) {
diff --git a/input.h b/input.h
index 360b65b..895ad61 100644
--- a/input.h