[PATCH 7/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 7/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.
TODO: get rid of the redundant "KMOD_" prefixes (needed in key mapping
file for compatibility with Vincent's keymap files) before merging
this.
Similarly to Vincent's patch:
* This removes support for using SDL key names. Names are now
supported only for modifier keys, and SDL scancodes need to be used
for the rest
* While mapping same PC key (scancode) with different modifiers is
accepted by parser, it will not work properly because ST key is
stored to KeysDown[] (which is indexed only by SDL scancode),
and taken from there in Keymap_KeyUp()
Unlike Vincent's patch:
* This always ignores NumLock in PC modifiers as that has special
functionality / key handling in Hatari
* There's no support for specifying mask for SDL modifiers in keymap
* User can specify multiple modifiers for the SDL key. It's not very
useful, but code for parsing modifiers has same logic as one used
for ST modifiers
---
src/keymap.c | 111 ++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 93 insertions(+), 18 deletions(-)
diff --git a/src/keymap.c b/src/keymap.c
index 5af6d263..a6bd2814 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -46,9 +46,13 @@ static const uint8_t DebounceExtendedKeys[] =
0 /* End of list */
};
+/* ignore capslock & numlock on SDL modifier matching */
+#define PC_MOD_MASK (~KMOD_NUM)
+
typedef struct
{
SDL_Scancode scancode;
+ SDL_Keymod mods;
} SDLKey;
static const struct
@@ -481,6 +485,7 @@ 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];
@@ -491,6 +496,9 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
if (mapping->pc.scancode != scancode)
continue;
+ if (mapping->pc.mods != (mods & PC_MOD_MASK))
+ continue;
+
KeysDown[scancode].mods = mapping->st.mods;
return UpdateMapping("keymap", scancode,
mapping->st.scancode);
@@ -502,6 +510,51 @@ static ST_Key* Keymap_RemapKeyToSTKey(const SDL_Keysym* pKeySym)
Keymap_SymbolicToStScanCode(pKeySym));
}
+/*-----------------------------------------------------------------------*/
+/**
+ * Parse SDL modifier name from 'name' and return 'mods' value with
+ * corresponding bit added to it, or return KMOD_NONE for error.
+ *
+ * NOTE: KMOD_CTRL / KMOD_SHIFT / KMOD_ALT / KMOD_GUI are composed of
+ * corresponding left & right variant bits, so they are left out
+ */
+static SDL_Keymod AddSdlModifier(SDL_Keymod mods, const char *name) {
+ struct {
+ SDL_Keymod mod;
+ const char *name;
+ } const keymodNames[] = {
+ { KMOD_LSHIFT, "KMOD_LSHIFT" },
+ { KMOD_RSHIFT, "KMOD_RSHIFT" },
+ { KMOD_LCTRL, "KMOD_LCTRL" },
+ { KMOD_RCTRL, "KMOD_RCTRL" },
+ { KMOD_LALT, "KMOD_LALT" },
+ { KMOD_RALT, "KMOD_RALT" },
+ { KMOD_LGUI, "KMOD_LGUI" },
+ { KMOD_RGUI, "KMOD_RGUI" },
+ { KMOD_CAPS, "KMOD_CAPS" },
+ { KMOD_MODE, "KMOD_MODE" },
+ { KMOD_CTRL, "KMOD_CTRL" },
+ };
+ SDL_Keymod mod;
+ int i;
+
+ for (i = 0; ARRAY_SIZE(keymodNames); i++)
+ {
+ if (strcmp(name, keymodNames[i].name) != 0)
+ continue;
+
+ mod = keymodNames[i].mod;
+ if (mod & mods)
+ {
+ Log_Printf(LOG_WARN, "PC/SDL modifier '%s' specified twice\n", name);
+ return KMOD_NONE;
+ }
+ return (mods | mod);
+ };
+ Log_Printf(LOG_ERROR, "unknown/unsupported PC/SDL modifier '%s'\n", name);
+ return KMOD_NONE;
+}
+
/*-----------------------------------------------------------------------*/
/**
@@ -510,30 +563,52 @@ 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);
+ if (isalpha(token[0]))
+ {
+ mods = AddSdlModifier(mods, token);
+ if (!mods)
+ return false;
+ continue;
+ }
+ 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
--------------76C8DE25C7D90F3D7A75426A
Content-Type: text/x-patch; charset=UTF-8;
name="0006-Add-trace-output-for-ST-key-modifiers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0006-Add-trace-output-for-ST-key-modifiers.patch"