diff options
Diffstat (limited to 'patches')
-rw-r--r-- | patches/libpicofe/0001-key-combos.patch | 199 |
1 files changed, 187 insertions, 12 deletions
diff --git a/patches/libpicofe/0001-key-combos.patch b/patches/libpicofe/0001-key-combos.patch index 7105fc3..b2e0819 100644 --- a/patches/libpicofe/0001-key-combos.patch +++ b/patches/libpicofe/0001-key-combos.patch @@ -1,8 +1,8 @@ diff --git a/in_sdl.c b/in_sdl.c -index a84c781..bab649a 100644 +index a84c781..bc0e79b 100644 --- a/in_sdl.c +++ b/in_sdl.c -@@ -19,11 +19,18 @@ +@@ -19,14 +19,24 @@ typedef unsigned long keybits_t; #define KEYBITS_WORD_BITS (sizeof(keybits_t) * 8) @@ -18,10 +18,40 @@ index a84c781..bab649a 100644 int joy_id; int axis_keydown[2]; + enum mod_state mod_state; ++ int allow_unbound_mods; ++ char *mods_bound; 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,139 @@ static int get_keystate(keybits_t *keystate, int sym) ++ short delayed_key; + }; + + static void (*ext_event_handler)(void *event); +@@ -184,6 +194,11 @@ static void in_sdl_probe(const in_drv_t *drv) + } + + state->drv = drv; ++ ++ if (pdata->mod_key) { ++ state->mods_bound = calloc(pdata->modmap_size, sizeof(char)); ++ } ++ + in_register(IN_SDL_PREFIX "keys", -1, state, SDLK_LAST, + key_names, 0); + +@@ -220,6 +235,11 @@ static void in_sdl_free(void *drv_data) + if (state != NULL) { + if (state->joy != NULL) + SDL_JoystickClose(state->joy); ++ ++ if (state->mods_bound != NULL) { ++ free(state->mods_bound); ++ } ++ + free(state); + } + } +@@ -259,6 +279,169 @@ static int get_keystate(keybits_t *keystate, int sym) return !!(*ks_word & mask); } @@ -73,7 +103,9 @@ index a84c781..bab649a 100644 + for (i = 0; i < pdata->modmap_size; i++) { + map = &pdata->mod_keymap[i]; + -+ if (get_keystate(keystate, map->inkey)) { ++ if (get_keystate(keystate, map->inkey) && ++ (state->allow_unbound_mods || ++ (state->mods_bound && state->mods_bound[i]))) { + state->mod_state = MOD_YES; + switch_key(event, keystate, map->inkey, map->outkey); + } @@ -93,9 +125,8 @@ index a84c781..bab649a 100644 + event->key.state = SDL_PRESSED; + SDL_PushEvent(event); + -+ event->type = SDL_KEYUP; -+ event->key.state = SDL_RELEASED; -+ SDL_PushEvent(event); ++ /* Delay keyup to force handling */ ++ state->delayed_key = event->key.keysym.sym; + } + break; + case MOD_YES: @@ -119,17 +150,24 @@ index a84c781..bab649a 100644 + break; + } + } else { ++ int found = 0; + for (i = 0; i < pdata->modmap_size; i++) { + map = &pdata->mod_keymap[i]; + -+ if (map->inkey == key) { ++ if (map->inkey == key && ++ (state->allow_unbound_mods || ++ (state->mods_bound && state->mods_bound[i]))) { + state->mod_state = MOD_YES; + + event->key.keysym.sym = map->outkey; + update_keystate(keystate, map->outkey, event->type == SDL_KEYDOWN); + SDL_PushEvent(event); ++ found = 1; + } + } ++ ++ if (!found) ++ SDL_PushEvent(event); + } +} + @@ -137,6 +175,7 @@ index a84c781..bab649a 100644 +{ + const struct in_pdata *pdata = state->drv->pdata; + SDL_Event events[10]; /* Must be bigger than events size in collect_events */ ++ SDL_Event delayed_event = {0}; + keybits_t keystate[SDLK_LAST / KEYBITS_WORD_BITS + 1]; + int count; + int has_events; @@ -145,6 +184,18 @@ index a84c781..bab649a 100644 + if (!pdata->mod_key) + return; + ++ if (!state->allow_unbound_mods && state->mods_bound) { ++ int bound = 0; ++ for (i = 0; i < pdata->modmap_size; i++) { ++ bound = state->mods_bound[i]; ++ if (bound) ++ break; ++ } ++ ++ if (!bound) ++ return; ++ } ++ + has_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask); + + if (!has_events) @@ -153,6 +204,15 @@ index a84c781..bab649a 100644 + memcpy(keystate, state->keystate, sizeof(keystate)); + + count = SDL_PeepEvents(events, (sizeof(events) / sizeof(events[0])), SDL_GETEVENT, mask); ++ ++ if (state->delayed_key != 0) { ++ delayed_event.type = SDL_KEYUP; ++ delayed_event.key.state = SDL_PRESSED; ++ delayed_event.key.keysym.sym = state->delayed_key; ++ SDL_PushEvent(&delayed_event); ++ state->delayed_key = 0; ++ } ++ + for (i = 0; i < count; i++) { + translate_combo_event(state, &events[i], keystate); + } @@ -161,7 +221,7 @@ index a84c781..bab649a 100644 static int handle_event(struct in_sdl_state *state, SDL_Event *event, int *kc_out, int *down_out, int *emu_out) { -@@ -363,6 +503,9 @@ static int collect_events(struct in_sdl_state *state, int *one_kc, int *one_down +@@ -363,6 +546,9 @@ static int collect_events(struct in_sdl_state *state, int *one_kc, int *one_down SDL_PumpEvents(); @@ -171,11 +231,99 @@ index a84c781..bab649a 100644 num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask); for (num_peeped_events = 0; num_peeped_events < num_events; num_peeped_events += count) { +@@ -406,12 +592,34 @@ out: + return retval; + } + ++static void update_modifier_binds(struct in_sdl_state *state, const int *binds) ++{ ++ int i, b; ++ const struct in_pdata *pdata = state->drv->pdata; ++ const struct mod_keymap *map; ++ ++ for (i = 0; i < pdata->modmap_size; i++) { ++ map = &pdata->mod_keymap[i]; ++ ++ for (b = 0; b < IN_BINDTYPE_COUNT; b++) { ++ state->mods_bound[i] = 0; ++ if (binds[IN_BIND_OFFS(map->outkey, b)]) { ++ state->mods_bound[i] = 1; ++ break; ++ } ++ } ++ } ++} ++ + static int in_sdl_update(void *drv_data, const int *binds, int *result) + { + struct in_sdl_state *state = drv_data; + keybits_t mask; + int i, sym, bit, b; + ++ if (state->mods_bound) ++ update_modifier_binds(state, binds); ++ + collect_events(state, NULL, NULL); + + for (i = 0; i < SDLK_LAST / KEYBITS_WORD_BITS + 1; i++) { +@@ -510,6 +718,35 @@ static int in_sdl_clean_binds(void *drv_data, int *binds, int *def_finds) + return cnt; + } + ++static int in_sdl_get_config(void *drv_data, int what, int *val) ++{ ++ struct in_sdl_state *state = drv_data; ++ ++ switch (what) { ++ case IN_CFG_ALLOW_UNBOUND_MOD_KEYS: ++ *val = state->allow_unbound_mods; ++ break; ++ default: ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int in_sdl_set_config(void *drv_data, int what, int val) ++{ ++ struct in_sdl_state *state = drv_data; ++ ++ switch (what) { ++ case IN_CFG_ALLOW_UNBOUND_MOD_KEYS: ++ state->allow_unbound_mods = val; ++ default: ++ return -1; ++ } ++ ++ return 0; ++} ++ + static const in_drv_t in_sdl_drv = { + .prefix = IN_SDL_PREFIX, + .probe = in_sdl_probe, +@@ -519,6 +756,8 @@ static const in_drv_t in_sdl_drv = { + .update_keycode = in_sdl_update_keycode, + .menu_translate = in_sdl_menu_translate, + .clean_binds = in_sdl_clean_binds, ++ .get_config = in_sdl_get_config, ++ .set_config = in_sdl_set_config, + }; + + int in_sdl_init(const struct in_pdata *pdata, void (*handler)(void *event)) diff --git a/input.h b/input.h -index 360b65b..895ad61 100644 +index 360b65b..f95ddf0 100644 --- a/input.h +++ b/input.h -@@ -110,6 +110,11 @@ struct menu_keymap { +@@ -59,6 +59,7 @@ + enum { + IN_CFG_BIND_COUNT = 0, + IN_CFG_DOES_COMBOS, ++ IN_CFG_ALLOW_UNBOUND_MOD_KEYS, + IN_CFG_BLOCKING, + IN_CFG_KEY_NAMES, + IN_CFG_ABS_DEAD_ZONE, /* dead zone for analog-digital mapping */ +@@ -110,6 +111,11 @@ struct menu_keymap { short pbtn; }; @@ -187,7 +335,7 @@ index 360b65b..895ad61 100644 struct in_pdata { const struct in_default_bind *defbinds; const struct menu_keymap *key_map; -@@ -117,6 +122,9 @@ struct in_pdata { +@@ -117,6 +123,9 @@ struct in_pdata { const struct menu_keymap *joy_map; size_t jmap_size; const char * const *key_names; @@ -197,3 +345,30 @@ index 360b65b..895ad61 100644 }; /* to be called by drivers */ +diff --git a/menu.c b/menu.c +index e91f84a..616daac 100644 +--- a/menu.c ++++ b/menu.c +@@ -1455,6 +1455,7 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_ + int i, sel = 0, menu_sel_max = opt_cnt - 1, does_combos = 0;
+ int dev_id, bind_dev_id, dev_count, kc, is_down, mkey;
+ int unbind, bindtype, mask_shift;
++ int allow_unbound_mods = 0;
+
+ for (i = 0, dev_id = -1, dev_count = 0; i < IN_MAX_DEVS; i++) {
+ if (in_get_dev_name(i, 1, 0) != NULL) {
+@@ -1515,10 +1516,14 @@ static void key_config_loop(const me_bind_action *opts, int opt_cnt, int player_ +
+ draw_key_config(opts, opt_cnt, player_idx, sel, dev_id, dev_count, 1);
+
++ in_get_config(bind_dev_id, IN_CFG_ALLOW_UNBOUND_MOD_KEYS, &allow_unbound_mods);
++ in_set_config_int(bind_dev_id, IN_CFG_ALLOW_UNBOUND_MOD_KEYS, 1);
+ /* wait for some up event */
+ for (is_down = 1; is_down; )
+ kc = in_update_keycode(&bind_dev_id, &is_down, NULL, -1);
+
++ in_set_config_int(bind_dev_id, IN_CFG_ALLOW_UNBOUND_MOD_KEYS, allow_unbound_mods);
++
+ i = count_bound_keys(bind_dev_id, opts[sel].mask << mask_shift, bindtype);
+ unbind = (i > 0);
+
|