diff options
| author | neonloop | 2021-08-12 15:29:39 +0000 | 
|---|---|---|
| committer | neonloop | 2021-08-12 15:29:39 +0000 | 
| commit | 4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51 (patch) | |
| tree | 88bf75a3ffac4017fe5124f935fe5e5f67dd6e48 /patches | |
| parent | c17d20ab28e0ac7dd527ff840559d96e98931a80 (diff) | |
| download | picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.gz picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.tar.bz2 picoarch-4f6bbfe3a4e16b3d322f9cd86a5f9ea1b8535d51.zip  | |
Adds combo key support to libpicofe
Diffstat (limited to 'patches')
| -rw-r--r-- | patches/libpicofe/0001-key-combos.patch | 157 | 
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 */  | 
