[PATCH 8/8] Support for specifying PC/SDL key modifiers in the mapping file |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
- Subject: [PATCH 8/8] Support for specifying PC/SDL key modifiers in the mapping file
- From: Eero Tamminen <oak@xxxxxxxxxxxxxx>
- Date: Tue, 19 Oct 2021 00:27:05 +0300
Loosely based on Vincent Barilliot's patch.
Unlike Vincent's patch:
* This supports using SDL scancode names in addition to modifier names
(as original Hatari code supported SDL key names)
* There's no support for specifying mask for SDL modifiers in keymap,
code just checks that at least specified modifier is pressed
* Special handling for SHIFT modifier, which matches either of
the SHIFT keys, so that one does not need two rules
* This has a lot more warnings and error checks
---
src/keymap.c | 139 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 121 insertions(+), 18 deletions(-)
diff --git a/src/keymap.c b/src/keymap.c
index bd6bec63..e5200739 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -49,6 +49,7 @@ static const uint8_t DebounceExtendedKeys[] =
typedef struct
{
SDL_Scancode scancode;
+ SDL_Keymod mods;
} SDLKey;
static const struct
@@ -491,9 +492,11 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
{
int i;
+ SDL_Keymod mods = pKeySym->mod;
for (i = 0; i < ARRAY_SIZE(LoadedKeymap); i++)
{
KeyMapping *mapping = &LoadedKeymap[i];
+ SDL_Keymod pcmod;
if (mapping->pc.scancode == 0)
break; /* End of table */
@@ -501,6 +504,17 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
if (mapping->pc.scancode != scancode)
continue;
+ pcmod = mapping->pc.mods;
+ /* (at least) one shift used? */
+ if (pcmod == KMOD_SHIFT)
+ {
+ if (!(mods & pcmod))
+ continue;
+ }
+ /* (at least) specified mod used? */
+ else if ((mods & pcmod) != pcmod)
+ continue;
+
KeysDown[scancode].mods = mapping->st.mods;
return UpdateMapping("keymap", scancode,
mapping->st.scancode);
@@ -513,6 +527,46 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
}
+/*-----------------------------------------------------------------------*/
+/**
+ * Parse SDL modifier name from 'name' and return its value, or
+ * zero for error.
+ */
+static SDL_Keymod GetSdlModifier(const char *name) {
+ struct {
+ SDL_Keymod mod;
+ const char *name;
+ } const keymodNames[] = {
+ { KMOD_LSHIFT, "LSHIFT" },
+ { KMOD_RSHIFT, "RSHIFT" },
+ { KMOD_SHIFT, "SHIFT" }, /* special case: either of above */
+
+ { KMOD_LCTRL, "LCTRL" },
+ { KMOD_RCTRL, "RCTRL" },
+ { KMOD_CTRL, "CTRL" }, /* both of above */
+
+ { KMOD_LALT, "LALT" },
+ { KMOD_RALT, "RALT" },
+ { KMOD_ALT, "ALT" }, /* both of above */
+
+ { KMOD_LGUI, "LGUI" },
+ { KMOD_RGUI, "RGUI" },
+ { KMOD_GUI, "GUI" }, /* both of above */
+
+ { KMOD_CAPS, "CAPS" },
+ { KMOD_MODE, "MODE" },
+ { KMOD_NUM, "NUM" },
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(keymodNames); i++)
+ {
+ if (strcmp(name, keymodNames[i].name) == 0)
+ return keymodNames[i].mod;
+ };
+ return 0;
+}
+
+
/*-----------------------------------------------------------------------*/
/**
* Fill "mapping" KeyMapping host part based on host "spec" string.
@@ -520,30 +574,79 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
*/
static bool HostSpecToKeymap(const char *spec, KeyMapping* mapping)
{
- int key;
+ char buf[64], *token, *saveptr, *endptr;
+ SDL_Scancode scancode = 0;
+ SDL_Keymod mods = 0;
+
if (!spec)
return false;
-
- key = atoi(spec); /* Direct key code? */
- if (key < 10)
+ if (strlcpy(buf, spec, sizeof(buf)) >= sizeof(buf))
{
- /* If it's not a valid number >= 10, then
- * assume we've got a symbolic key name
- */
- int offset = 0;
- /* quoted character (e.g. comment line char)? */
- if (*spec == '\\' && strlen(spec) == 2)
- offset = 1;
- key = Keymap_GetKeyFromName(spec+offset);
+ Log_Printf(LOG_ERROR, "PC/SDL scancode spec '%s' too long\n", spec);
+ return false;
}
- if (key < 8)
+
+ scancode = mods = 0;
+ for (token = strtok_r(buf, "|", &saveptr);
+ token;
+ token = strtok_r(NULL, "|", &saveptr))
{
- Log_Printf(LOG_WARN, "Invalid PC key: '%s' (%d >= 8)\n",
- spec, key);
- return false;
+ token = Str_Trim(token);
+ /* text description? */
+ if (isalpha(token[0]))
+ {
+ SDL_Scancode code;
+ SDL_Keymod mod;
+
+ /* is it modifier? */
+ mod = GetSdlModifier(token);
+ if (mod)
+ {
+ if (mods)
+ {
+ Log_Printf(LOG_ERROR, "extra '%s', PC/SDL modifier already set\n", token);
+ return false;
+ }
+ mods = mod;
+ continue;
+ }
+ /* is it non-modifier key? */
+ code = SDL_GetScancodeFromName(token);
+ if (code)
+ {
+ if (scancode)
+ {
+ Log_Printf(LOG_ERROR, "extra '%s', PC/SDL scancode already set\n", token);
+ return false;
+ }
+ scancode = code;
+ continue;
+ }
+ Log_Printf(LOG_ERROR, "unknown PC/SDL key/modifier name '%s'\n", token);
+ return false;
+ }
+ /* no => numerical scancode */
+ if (scancode)
+ {
+ Log_Printf(LOG_WARN, "extra '%s', PC/SDL scancode already set\n", token);
+ return false;
+ }
+ scancode = strtol(token, &endptr, 10);
+ if (!scancode)
+ {
+ Log_Printf(LOG_ERROR, "invalid PC/SDL scancode '%s'\n", token);
+ return false;
+ }
+ if (*endptr)
+ {
+ Log_Printf(LOG_WARN, "'%s' garbage at end of '%s' PC/SDL scancode\n",
+ endptr, token);
+ return false;
+ }
}
- mapping->pc.scancode = key;
- return true;
+ mapping->pc.scancode = scancode;
+ mapping->pc.mods = mods;
+ return (scancode > 0);
}
--
2.30.2
--------------F1FA3BEB0519731AA569A677
Content-Type: text/x-patch; charset=UTF-8;
name="0007-Add-trace-output-for-ST-key-modifiers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0007-Add-trace-output-for-ST-key-modifiers.patch"